Roy Hashimoto created HTTPCORE-601:
--------------------------------------

             Summary: SSLIOSession.close() is never called for async server 
handling HTTP1
                 Key: HTTPCORE-601
                 URL: https://issues.apache.org/jira/browse/HTTPCORE-601
             Project: HttpComponents HttpCore
          Issue Type: Bug
          Components: HttpCore NIO
    Affects Versions: 5.0-beta8
         Environment: macOS Mojave, Debian Jessie
            Reporter: Roy Hashimoto
         Attachments: ConscryptTest.java

On 5.0, an asynchronous server handling an HTTP1 request never calls 
{{SSLIOSession.close()}}. The attached sample server program exhibits the 
problem. To test:
 # Set a breakpoint in {{SSLIOSession.close()}}.
 # Make some requests.

The expectation is for the breakpoint to be triggered when the connection ends. 
The observed behavior is that the breakpoint is never reached.

The sample program uses Conscrypt (org.conscrypt:conscrypt-openjdk-uber:2.2.1) 
but the root problem occurs with any JSSE provider including the default. There 
is an additional bad side effect with Conscrypt, however, which is that the 
program spins in the selection loop and consumes excessive CPU.

When {{AbstractHttp1StreamDuplexer.requestShutdown()}} sets {{OP_WRITE}}, this 
code in {{onOutput()}} should call {{SSLIOSession.close()}}:

[https://github.com/apache/httpcomponents-core/blob/44cab548cb4e15d56235aa12eaf0898d028351d0/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java#L366-L373]

This doesn't happen because {{SSLIOSession.isAppOutputReady()}} returns false 
here:

[https://github.com/apache/httpcomponents-core/blob/44cab548cb4e15d56235aa12eaf0898d028351d0/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalDataChannel.java#L139]

which happens because {{status}} is {{CLOSING}} and 
{{sslEngine.getHandshakeStatus()}} returns {{NEED_WRAP}}. So {{onOutput()}} is 
not called after {{requestShutdown()}} and {{OP_WRITE}} remains set. On 
Conscrypt, selection on OP_WRITE keeps succeeding which causes the spin.

I tried hacking SSLIOSession.isAppOutputReady():
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
@@ -523,8 +523,9 @@ public boolean isAppOutputReady() throws IOException {
         this.session.getLock().lock();
         try {
             return (this.appEventMask & SelectionKey.OP_WRITE) > 0
-                    && this.status == ACTIVE
-                    && this.sslEngine.getHandshakeStatus() == 
HandshakeStatus.NOT_HANDSHAKING;
+                    && ((this.status == ACTIVE
+                         && this.sslEngine.getHandshakeStatus() == 
HandshakeStatus.NOT_HANDSHAKING)
+                        || this.status == CLOSING);
         } finally {
             this.session.getLock().unlock();
         }
This is probably not the appropriate fix, but it does call 
{{SSLIOSession.close()}} and does not spin with Conscrypt so something that 
achieves that should work.



--
This message was sent by Atlassian Jira
(v8.3.2#803003)

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

Reply via email to