[ 
https://issues.apache.org/jira/browse/HTTPCORE-601?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16930021#comment-16930021
 ] 

Oleg Kalnichevski commented on HTTPCORE-601:
--------------------------------------------

[~rhashimoto] I was able to reproduce the issue with Conscrypt 2.2.1 but not 
with Conscrypt 1.4.2 or any Oracle JSSE providers (tried Java 1.8 and Java 
11.0.3). 

At the moment this looks to me very much like a bug in Conscrypt 2.2.1.

What is happening is this:
# The client closes the session on its end after having executed the entire 
message exchange
# {{#updateEventMask}} detects the end of stream from the opposite endpoint and 
puts the session into the CLOSING state.
# {{#updateEventMask}} detects that the session is in the CLOSING state and 
there is no more outgoing data and closes outbound stream with 
{{SSLEngine#closeOutbound()}}
# The Conscrypt engine however does not seem to react to this method. It still 
returns false from {{SSLEngine#isOutboundDone()}} but also remains in the 
{{NOT_HANDSHAKING}} state, which does make any sense to me and looks wrong.
# The session loops forever waiting for the SSL engine either to report 
outbound stream as done or start handshaking.

I will debug Conscrypt code before reaching any conclusion and would also see 
if there is a reasonable defensive strategy against such behavior.

What I do not understand is why you think that {{SSLIOSession#close()}} never 
getting called is a problem. The {{SSLIOSession}} is supposed to shut down 
itself if the opposite endpoint closes the session on its end.

Please comment. 

Oleg

> 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
>            Assignee: Oleg Kalnichevski
>            Priority: Major
>         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: dev-unsubscr...@hc.apache.org
For additional commands, e-mail: dev-h...@hc.apache.org

Reply via email to