Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shutdownOutput() for SSL connections prematurely closes the Channel #1502

Merged
merged 1 commit into from
May 5, 2021

Conversation

idelpivnitskiy
Copy link
Member

@idelpivnitskiy idelpivnitskiy commented Apr 19, 2021

Motivation:

Before RequestResponseCloseHandler invokes shutdownOutput(), it forces
SslHandler to close SSLEngine and send close_notify to the remote peer.
Because SSLEngine is closed, SslHandler will generate
SslCloseCompletionEvent on the next read regardless of receiving the
close_notify alert from the remote peer or not. This premature event is
handled incorrectly by the DefaultNettyConnection and forces the channel
closure, breaking graceful closure and connection: close handling on the
server-side.

Modifications:

  • Move handling of SslCloseCompletionEvent to the CloseHandler that is
    aware of the current state;
  • RequestResponseCloseHandler now ignores SslCloseCompletionEvent if it
    knows that the outbound was shutdown. It will wait for the FIN from
    remote peer to finish graceful closure;
  • Enhance RequestResponseCloseHandlerTest to validate new behavior;
  • Add logging for NonPipelinedCloseHandler;

Result:

  1. shutdownOutput() does not break graceful closure.
  2. Fixes GracefulConnectionClosureHandlingTest.closePipelinedAfterTwoRequestsSentBeforeAnyResponseReceived test failure #1192. Use-case
    [4: protocol=HTTP_1 initiateClosureFromClient=false useUds=false viaProxy=true]
    is not flaky anymore.
  3. Fixes ConnectionCloseHeaderHandlingTest$PipelinedRequestsTest.serverCloseSecondPipelinedRequestWriteAborted test failure #1277.
  4. Fixes ConnectionCloseHeaderHandlingTest$PipelinedRequestsTest.serverCloseTwoPipelinedRequestsSentBeforeFirstResponse test failure #1323.

Motivation:

Before `RequestResponseCloseHandler` invokes `shutdownOutput()`, it forces
`SslHandler` to close `SSLEngine` and send `close_notify` to the remote peer.
Because `SSLEngine` is closed, `SslHandler` will generate
`SslCloseCompletionEvent` on the next read regardless of receiving the
`close_notify` alert from the remote peer or not. This premature event is
handled incorrectly by the `DefaultNettyConnection` and forces the channel
closure, breaking graceful closure handling on the server-side.

Modifications:

- Move handling of `SslCloseCompletionEvent` to the `CloseHandler` that is
aware of the current state;
- `RequestResponseCloseHandler` now ignores `SslCloseCompletionEvent` if it
knows that the outbound was shutdown. It will wait for the `FIN` from
remote peer to finish graceful closure;
- Enhance `RequestResponseCloseHandlerTest` to validate new behavior;

Result:

1. `shutdownOutput()` does not break graceful closure.
2. apple#1192 use-case
`[4: protocol=HTTP_1 initiateClosureFromClient=false useUds=false viaProxy=true]`
is not flaky anymore.
Copy link
Contributor

@tkountis tkountis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but better someone with Netty experience do the approval.

@idelpivnitskiy
Copy link
Member Author

@Scottmitch can you take a look please?

@idelpivnitskiy idelpivnitskiy merged commit 2bc89b5 into apple:main May 5, 2021
@idelpivnitskiy idelpivnitskiy deleted the so_cn branch May 5, 2021 22:51
@idelpivnitskiy
Copy link
Member Author

Discussed with @Scottmitch offline

bondolo pushed a commit to bondolo/servicetalk that referenced this pull request May 7, 2021
…apple#1502)

Motivation:

Before `RequestResponseCloseHandler` invokes `shutdownOutput()`, it forces
`SslHandler` to close `SSLEngine` and send `close_notify` to the remote peer.
Because `SSLEngine` is closed, `SslHandler` will generate
`SslCloseCompletionEvent` on the next read regardless of receiving the
`close_notify` alert from the remote peer or not. This premature event is
handled incorrectly by the `DefaultNettyConnection` and forces the channel
closure, breaking graceful closure handling on the server-side.

Modifications:

- Move handling of `SslCloseCompletionEvent` to the `CloseHandler` that is
aware of the current state;
- `RequestResponseCloseHandler` now ignores `SslCloseCompletionEvent` if it
knows that the outbound was shutdown. It will wait for the `FIN` from
remote peer to finish graceful closure;
- Enhance `RequestResponseCloseHandlerTest` to validate new behavior;

Result:

1. `shutdownOutput()` does not break graceful closure.
2. apple#1192 use-case
`[4: protocol=HTTP_1 initiateClosureFromClient=false useUds=false viaProxy=true]`
is not flaky anymore.
hbelmiro pushed a commit to hbelmiro/servicetalk that referenced this pull request May 23, 2021
…apple#1502)

Motivation:

Before `RequestResponseCloseHandler` invokes `shutdownOutput()`, it forces
`SslHandler` to close `SSLEngine` and send `close_notify` to the remote peer.
Because `SSLEngine` is closed, `SslHandler` will generate
`SslCloseCompletionEvent` on the next read regardless of receiving the
`close_notify` alert from the remote peer or not. This premature event is
handled incorrectly by the `DefaultNettyConnection` and forces the channel
closure, breaking graceful closure handling on the server-side.

Modifications:

- Move handling of `SslCloseCompletionEvent` to the `CloseHandler` that is
aware of the current state;
- `RequestResponseCloseHandler` now ignores `SslCloseCompletionEvent` if it
knows that the outbound was shutdown. It will wait for the `FIN` from
remote peer to finish graceful closure;
- Enhance `RequestResponseCloseHandlerTest` to validate new behavior;

Result:

1. `shutdownOutput()` does not break graceful closure.
2. apple#1192 use-case
`[4: protocol=HTTP_1 initiateClosureFromClient=false useUds=false viaProxy=true]`
is not flaky anymore.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment