8162521: java/net/Authenticator/B4933582.sh fails intermittently with BindException
Reviewed-by: dfuchs
--- a/jdk/test/java/net/Authenticator/B4933582.java Thu Dec 01 06:38:46 2016 -0800
+++ b/jdk/test/java/net/Authenticator/B4933582.java Thu Dec 01 06:54:01 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,6 +21,15 @@
* questions.
*/
+/*
+ * @test
+ * @bug 4933582
+ * @library ../../../sun/net/www/httptest
+ * @modules java.base/sun.net.www
+ * java.base/sun.net.www.protocol.http
+ * @build HttpCallback HttpTransaction TestHttpServer B4933582
+ * @run main/othervm B4933582
+ */
import java.io.*;
import java.net.*;
import java.util.*;
@@ -44,7 +53,7 @@
req.orderlyClose();
}
- static boolean firstTime = true;
+ static volatile boolean firstTime = true;
public void request (HttpTransaction req) {
try {
@@ -114,43 +123,67 @@
URL url = new URL (u);
System.out.println ("client opening connection to: " + u);
URLConnection urlc = url.openConnection ();
- InputStream is = urlc.getInputStream ();
- read (is);
- is.close();
+ try(InputStream is = urlc.getInputStream ()) {
+ read (is);
+ }
}
static TestHttpServer server;
public static void main (String[] args) throws Exception {
- firstTime = args[0].equals ("first");
MyAuthenticator auth = new MyAuthenticator ();
Authenticator.setDefault (auth);
CacheImpl cache;
try {
- if (firstTime) {
- server = new TestHttpServer (new B4933582(), 1, 10, 0);
- cache = new CacheImpl (server.getLocalPort());
- } else {
- cache = new CacheImpl ();
- server = new TestHttpServer(new B4933582(), 1, 10, cache.getPort());
- }
+ server = new TestHttpServer (new B4933582(), 1, 10, 0);
+ cache = new CacheImpl (server.getLocalPort());
AuthCacheValue.setAuthCache (cache);
- System.out.println ("Server: listening on port: " + server.getLocalPort());
client ("http://localhost:"+server.getLocalPort()+"/d1/foo.html");
- } catch (Exception e) {
+ } finally {
if (server != null) {
server.terminate();
}
- throw e;
}
+
int f = auth.getCount();
- if (firstTime && f != 1) {
- except ("Authenticator was called "+f+" times. Should be 1");
+ if (f != 1) {
+ except("Authenticator was called " + f + " times. Should be 1");
}
- if (!firstTime && f != 0) {
- except ("Authenticator was called "+f+" times. Should be 0");
+
+ firstTime = false;
+
+ int retries = 0;
+ cache = new CacheImpl();
+ while (true) {
+ try {
+ server = new TestHttpServer(new B4933582(), 1, 10,
+ cache.getPort());
+ break;
+ } catch (BindException e) {
+ if (retries++ < 5) {
+ Thread.sleep(200L);
+ System.out.println("BindException \"" + e.getMessage()
+ + "\", retrying...");
+ continue;
+ } else {
+ throw e;
+ }
+ }
}
- server.terminate();
+
+ try {
+ AuthCacheValue.setAuthCache(cache);
+ client("http://localhost:" + server.getLocalPort() + "/d1/foo.html");
+ } finally {
+ if (server != null) {
+ server.terminate();
+ }
+ }
+
+ f = auth.getCount();
+ if (f != 1) {
+ except("Authenticator was called " + f + " times. Should be 1");
+ }
}
public static void except (String s) {
@@ -163,7 +196,7 @@
super ();
}
- int count = 0;
+ volatile int count = 0;
public PasswordAuthentication getPasswordAuthentication () {
PasswordAuthentication pw;
@@ -178,7 +211,7 @@
}
static class CacheImpl extends AuthCacheImpl {
- HashMap map;
+ HashMap<String,LinkedList<AuthCacheValue>> map;
int port; // need to store the port number the server is using
CacheImpl () throws IOException {
@@ -190,20 +223,18 @@
this.port = port;
File src = new File ("cache.ser");
if (src.exists()) {
- ObjectInputStream is = new ObjectInputStream (
- new FileInputStream (src)
- );
- try {
- map = (HashMap)is.readObject ();
+ try (ObjectInputStream is = new ObjectInputStream(
+ new FileInputStream(src))) {
+ map = (HashMap<String,LinkedList<AuthCacheValue>>)is
+ .readObject();
this.port = (Integer)is.readObject ();
System.out.println ("read port from file " + port);
} catch (ClassNotFoundException e) {
assert false;
}
- is.close();
System.out.println ("setMap from cache.ser");
} else {
- map = new HashMap();
+ map = new HashMap<>();
}
setMap (map);
}
@@ -213,20 +244,22 @@
}
private void writeMap () {
+ File dst = new File("cache.ser");
try {
- File dst = new File ("cache.ser");
dst.delete();
if (!dst.createNewFile()) {
return;
}
- ObjectOutputStream os = new ObjectOutputStream (
- new FileOutputStream (dst)
- );
+ } catch (IOException e) {
+ }
+
+ try (ObjectOutputStream os = new ObjectOutputStream(
+ new FileOutputStream(dst))) {
os.writeObject(map);
os.writeObject(port);
- System.out.println ("wrote port " + port);
- os.close();
- } catch (IOException e) {}
+ System.out.println("wrote port " + port);
+ } catch (IOException e) {
+ }
}
public void put (String pkey, AuthCacheValue value) {
--- a/jdk/test/java/net/Authenticator/B4933582.sh Thu Dec 01 06:38:46 2016 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-#
-# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 4933582
-
-OS=`uname -s`
-case "$OS" in
- SunOS | Linux | Darwin | AIX )
- PS=":"
- FS="/"
- ;;
- CYGWIN* )
- PS=";"
- FS="/"
- ;;
- Windows* )
- PS=";"
- FS="\\"
- ;;
- * )
- echo "Unrecognized system!"
- exit 1;
- ;;
-esac
-
-EXTRAOPTS="--add-exports java.base/sun.net.www=ALL-UNNAMED --add-exports java.base/sun.net.www.protocol.http=ALL-UNNAMED"
-export EXTRAOPTS
-
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . \
- -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest" ${TESTSRC}${FS}B4933582.java
-rm -f cache.ser auth.save
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 first
-${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 second
--- a/jdk/test/sun/net/www/httptest/TestHttpServer.java Thu Dec 01 06:38:46 2016 -0800
+++ b/jdk/test/sun/net/www/httptest/TestHttpServer.java Thu Dec 01 06:54:01 2016 -0800
@@ -116,15 +116,26 @@
}
}
- /** Tell all threads in the server to exit within 5 seconds.
- * This is an abortive termination. Just prior to the thread exiting
- * all channels in that thread waiting to be closed are forceably closed.
+ /**
+ * Tell all threads in the server to exit within 5 seconds.
+ * This is an abortive termination. Just prior to the thread exiting
+ * all channels in that thread waiting to be closed are forceably closed.
+ * @throws InterruptedException
*/
public void terminate () {
for (int i=0; i<threads; i++) {
servers[i].terminate ();
}
+
+ for (int i = 0; i < threads; i++) {
+ try {
+ servers[i].join();
+ } catch (InterruptedException e) {
+ System.err.println("Unexpected InterruptedException during terminating server");
+ throw new RuntimeException(e);
+ }
+ }
}
/**
@@ -147,7 +158,7 @@
int maxconn;
int nconn;
ClosedChannelList clist;
- boolean shutdown;
+ volatile boolean shutdown;
Server (HttpCallback cb, ServerSocketChannel schan, int maxconn) {
this.schan = schan;
@@ -166,18 +177,18 @@
}
/* Stop the thread as soon as possible */
- public synchronized void terminate () {
+ public void terminate () {
shutdown = true;
}
public void run () {
try {
while (true) {
- selector.select (1000);
- Set selected = selector.selectedKeys();
- Iterator iter = selected.iterator();
+ selector.select(1000);
+ Set<SelectionKey> selected = selector.selectedKeys();
+ Iterator<SelectionKey> iter = selected.iterator();
while (iter.hasNext()) {
- key = (SelectionKey)iter.next();
+ key = iter.next();
if (key.equals (listenerKey)) {
SocketChannel sock = schan.accept ();
if (sock == null) {
@@ -200,7 +211,7 @@
SocketChannel chan = (SocketChannel) key.channel();
System.out.println("SERVER: connection readable. chan[" + chan + "]");
if (key.attachment() != null) {
- System.out.println("Server: comsume");
+ System.out.println("Server: consume");
closed = consume (chan);
} else {
closed = read (chan, key);
@@ -219,7 +230,16 @@
}
clist.check();
if (shutdown) {
+ System.out.println("Force to Shutdown");
+ SelectionKey sKey = schan.keyFor(selector);
+ if (sKey != null) {
+ sKey.cancel();
+ }
+
clist.terminate ();
+ selector.close();
+ schan.socket().close();
+ schan.close();
return;
}
}
@@ -726,3 +746,4 @@
}
}
}
+