diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java b/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java index 1d8cb013295cc..e1725aa92d592 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ConnectionPool.java @@ -205,32 +205,38 @@ void returnToPool(HttpConnection conn, Deadline now, long keepAlive) { // it's possible that cleanup may have been called. HttpConnection toClose = null; + boolean stopping = false; stateLock.lock(); try { if (cleanup.isDone()) { return; - } else if (stopped) { - conn.close(); - return; - } - if (MAX_POOL_SIZE > 0 && expiryList.size() >= MAX_POOL_SIZE) { - toClose = expiryList.removeOldest(); - if (toClose != null) removeFromPool(toClose); - } - if (conn instanceof PlainHttpConnection) { - putConnection(conn, plainPool); + } else if (stopping = stopped) { + toClose = conn; } else { - assert conn.isSecure(); - putConnection(conn, sslPool); + if (MAX_POOL_SIZE > 0 && expiryList.size() >= MAX_POOL_SIZE) { + toClose = expiryList.removeOldest(); + if (toClose != null) removeFromPool(toClose); + } + if (conn instanceof PlainHttpConnection) { + putConnection(conn, plainPool); + } else { + assert conn.isSecure(); + putConnection(conn, sslPool); + } + expiryList.add(conn, now, keepAlive); } - expiryList.add(conn, now, keepAlive); } finally { stateLock.unlock(); } if (toClose != null) { if (debug.on()) { - debug.log("Maximum pool size reached: removing oldest connection %s", - toClose.dbgString()); + if (stopping) { + debug.log("Stopping: close connection %s", + toClose.dbgString()); + } else { + debug.log("Maximum pool size reached: removing oldest connection %s", + toClose.dbgString()); + } } close(toClose); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java index af9fd3b96ba51..1b9a79b8803a7 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java @@ -1333,6 +1333,13 @@ String getName() { // Only called by the selector manager thread private void shutdown() { + // first stop the client to avoid seeing exceptions + // about "selector manager closed" + Log.logTrace("{0}: stopping", owner.dbgTag); + try { + owner.stop(); + } catch (Throwable ignored) { + } try { lock.lock(); try { @@ -1345,6 +1352,7 @@ private void shutdown() { } } catch (IOException ignored) { } finally { + // cleanup anything that might have been left behind owner.stop(); } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java index e705aae72a14e..45d242df6717b 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java @@ -311,20 +311,20 @@ void close(Throwable cause) { var connectTimerEvent = this.connectTimerEvent; if (connectTimerEvent != null) client().cancelTimer(connectTimerEvent); - if (Log.channel()) { - Log.logChannel("Closing channel: " + chan); - } - try { - tube.signalClosed(errorRef.get()); - chan.close(); - } finally { - client().connectionClosed(this); - } + } finally { + stateLock.unlock(); + } + if (Log.channel()) { + Log.logChannel("Closing channel: " + chan); + } + try { + tube.signalClosed(errorRef.get()); + chan.close(); } catch (IOException e) { debug.log("Closing resulted in " + e); Log.logTrace("Closing resulted in " + e); } finally { - stateLock.unlock(); + client().connectionClosed(this); } }