Hunter Presnall created HTTPCORE-528:
----------------------------------------

             Summary: Infinite loop on server disconnect
                 Key: HTTPCORE-528
                 URL: https://issues.apache.org/jira/browse/HTTPCORE-528
             Project: HttpComponents HttpCore
          Issue Type: Bug
          Components: HttpCore NIO
    Affects Versions: 4.4.9
         Environment: bare metal Ubuntu 16.04 with kernel 4.4; 
openjdk1.8.0_172_x64 and Oracle jdk1.8.0_162_x64
CentOs Docker container with 3.10; openjdk1.8.0_172_x64
macOS 10.13.5; openjdk1.8.0_172_x64

            Reporter: Hunter Presnall
         Attachments: httpdebug.log

I am seeing HTTP NIO client get into an infinite loop after the server 
disconnections the connection. See the log output attached; note some content 
removed for privacy.

 

Note that the HttpAsyncClient has returned the response and the application has 
completely processed it. The client maintains the connection, as expected, 
since the response included `Keep-Alive: timeout=5`. Five seconds after 
everything is complete, the _server_ closes the TCP connection. The client 
reacts accordingly: the selector wakes up, does a read of -1 bytes, closes the 
session and sets a 1 second timeout to close the connection in.

 

The infinite loop occurs because the selector.select() call _constantly_ 
returns in AbstractIOReactor.execute()

readyCount == 1, so events are processed

processEvent() notes the key is readable and calls:

  session.resetLastRead()

  readable(key);

Because resetLastRead() is constantly updated, the 1 second timeout is never 
reached and AbstractIOReactor.timeoutCheck() can never call sessionTimedOut() 
or close the connection.

 

Note the entire time this is happening, netstat shows the connection is in 
CLOSE_WAIT state. The infinite loop continues until the OS keepalive timeout is 
reached and the connection is cleaned by the OS.

I am not sure if this epoll / selector behavior is expected or not. However, I 
have replicated this issue in multiple environments. It seems like the async 
client should handle this by detecting the condition and closing the connection.

 

Other notes from this infinite loop state:

SSLIOSession.updateEventMask() never closes the session either since the state 
remains `CLOSING`

AbstractIODispatch.inputReady() _does not_  read any data from the connection 
since ssliosession.isAppInputReady() evaluates to false.

SelectionKeyImpl.interestOps remains 1 (`OP_READ`)



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to