jersey icon indicating copy to clipboard operation
jersey copied to clipboard

JdkConnector does not properly cleanup ERROR state connections

Open dude-abides opened this issue 1 year ago • 3 comments

I am using Dropwizard 4 (Jersey 3.0.5) on Java 17. This problem exists in 3.0.12 as well.

When an HttpConnection transitions to ERROR from IDLE state, the connection gets closed but not removed from DestinationConnectionPool. This results in the next request failing regardless of whether the server has been restarted.

My guess is that cleanClosedConnection should be called at: https://github.com/eclipse-ee4j/jersey/blob/fc78757d0b2ece3f03e2c35f709fe070c350fc96/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/DestinationConnectionPool.java#L287

dude-abides avatar Apr 10 '24 11:04 dude-abides

@dude-abides which is the request or how do you receive the ERROR state after which a connection is not removed?

senivam avatar Apr 25 '24 08:04 senivam

Step to recreate

  1. Run a server and client on the same machine
  2. Make one request to server successfully
  3. Shutdown the server (forced)
  4. Make another request to the server

dude-abides avatar Apr 25 '24 11:04 dude-abides

So, I've retried the described behavior. The main difference I've got is: When the server is being shut down between requests, the request that goes to nowhere results in the ERROR state but in the DestinationConnectionPool it hits the

case CONNECTING: {
                            removeAllPendingWithError(connection.getError());
                            return;
                        }

case because the oldState is CONNECTING thus the removeAllPendingWithError(connection.getError()); properly cleans all connections and the next request which runs to the already started server passes OK. Furthermore, the line in the DestinationConnectionPool you are referring to handles unexpected behavior by throwing the IllegalStateException("Illegal state transition, old state: " + oldState + " new state: " + newState); exception which terminates all connections in the flow instantly. I'm not sure, how it's possible to bypass the CONNECTING state from the IDLE. All my investigations resulted in the flow that defines the IDLE state as the primary and then in case of sending the request the flow goes to the CONNECTING state. If you have some special use case that somehow manages to violate this sequence please share it I'll try to make it impossible :)

senivam avatar Apr 26 '24 18:04 senivam