8299058: AssertionError in sun.net.httpserver.ServerImpl when connection is idle

Reviewed-by: jpai, michaelm, dfuchs
This commit is contained in:
Daniel Jeliński 2023-10-31 15:53:28 +00:00
parent 2d5829afbc
commit 47624f6fc6

View File

@ -57,7 +57,6 @@ import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.Timer; import java.util.Timer;
@ -522,14 +521,15 @@ class ServerImpl {
key.cancel(); key.cancel();
chan.configureBlocking (true); chan.configureBlocking (true);
// check if connection is being closed
if (newlyAcceptedConnections.remove(conn) if (newlyAcceptedConnections.remove(conn)
|| idleConnections.remove(conn)) { || idleConnections.remove(conn)) {
// was either a newly accepted connection or an idle // was either a newly accepted connection or an idle
// connection. In either case, we mark that the request // connection. In either case, we mark that the request
// has now started on this connection. // has now started on this connection.
requestStarted(conn); requestStarted(conn);
}
handle (chan, conn); handle (chan, conn);
}
} else { } else {
assert false : "Unexpected non-readable key:" + key; assert false : "Unexpected non-readable key:" + key;
} }
@ -1019,31 +1019,25 @@ class ServerImpl {
*/ */
class IdleTimeoutTask extends TimerTask { class IdleTimeoutTask extends TimerTask {
public void run () { public void run () {
ArrayList<HttpConnection> toClose = new ArrayList<>(); closeConnections(idleConnections, IDLE_INTERVAL);
final long currentTime = System.currentTimeMillis();
synchronized (idleConnections) {
final Iterator<HttpConnection> it = idleConnections.iterator();
while (it.hasNext()) {
final HttpConnection c = it.next();
if (currentTime - c.idleStartTime >= IDLE_INTERVAL) {
toClose.add(c);
it.remove();
}
}
}
// if any newly accepted connection has been idle (i.e. no byte has been sent on that // if any newly accepted connection has been idle (i.e. no byte has been sent on that
// connection during the configured idle timeout period) then close it as well // connection during the configured idle timeout period) then close it as well
synchronized (newlyAcceptedConnections) { closeConnections(newlyAcceptedConnections, NEWLY_ACCEPTED_CONN_IDLE_INTERVAL);
final Iterator<HttpConnection> it = newlyAcceptedConnections.iterator(); }
while (it.hasNext()) {
final HttpConnection c = it.next(); private void closeConnections(Set<HttpConnection> connections, long idleInterval) {
if (currentTime - c.idleStartTime >= NEWLY_ACCEPTED_CONN_IDLE_INTERVAL) { long currentTime = System.currentTimeMillis();
ArrayList<HttpConnection> toClose = new ArrayList<>();
connections.forEach(c -> {
if (currentTime - c.idleStartTime >= idleInterval) {
toClose.add(c); toClose.add(c);
it.remove();
}
}
} }
});
for (HttpConnection c : toClose) { for (HttpConnection c : toClose) {
// check if connection still idle
if (currentTime - c.idleStartTime >= idleInterval &&
connections.remove(c)) {
allConnections.remove(c); allConnections.remove(c);
c.close(); c.close();
if (logger.isLoggable(Level.TRACE)) { if (logger.isLoggable(Level.TRACE)) {
@ -1052,6 +1046,7 @@ class ServerImpl {
} }
} }
} }
}
/** /**
* Responsible for closing connections which have timed out while in REQUEST or RESPONSE state * Responsible for closing connections which have timed out while in REQUEST or RESPONSE state