Skip to content
This repository has been archived by the owner on Apr 16, 2020. It is now read-only.

how to gracefully close client connection? #113

Open
ian-p-cooke opened this issue Feb 12, 2019 · 4 comments
Open

how to gracefully close client connection? #113

ian-p-cooke opened this issue Feb 12, 2019 · 4 comments

Comments

@ian-p-cooke
Copy link

What's the right way to close/shutdown a client? With my current implementation I'm not doing anything in particular and the server side always results in an error like H2 Serve Error: Protocol(Error { kind: Io(Os { code: 10053, kind: ConnectionAborted, message: "An established connection was aborted by the software in your host machine." }) }). This is with a client and server both running on Windows implemented with tower-grpc and tokio_rustls.

I've run into a similar issue before with Cap'n Proto RPC over TLS and it was related to AsyncWrite's shutdown. I'm still digging through the source to figure out where that should be called but it seems like a Client should have a shutdown/disconnect method that's passed down to H2 to shutdown the connection.

see capnproto/capnp-rpc-rust#23 for reference.

@ian-p-cooke
Copy link
Author

I think a 'disconnect' or 'shutdown' method would be nice but I have a workaround for now: I implemented a wrapper around the TlsStream that spawns a future that will shutdown the connection when it is dropped. It seems hacky and leads to a lock around every call for Read/Write/AsyncRead/AsyncWrite but it does show that if shutdown is called then I don't get an error on the server when I run my client.

https://gist.github.com/ian-p-cooke/73c454a21e7dc7309dcc43680e8e7769

@seanmonstar
Copy link
Contributor

There is graceful goway built-in to h2, and should work in most cases by simply dropping the client handle. When the h2::client::Connection detects no more handles exist, it should send a GOAWAY frame and shutdown.

Do you have any more code we could look at?

@ian-p-cooke
Copy link
Author

I have an example here: https://github.com/ian-p-cooke/tower-grpc-tls-client-auth-example

so, weird thing is, when I was verifying that my example had the same problem I found that if I run in release mode it doesn't happen. So 'client' can be debug or release, doesn't matter. but if 'server' is debug then the output of the example is:

REQUEST = Request { metadata: MetadataMap { headers: {"te": "trailers", "content-type": "application/grpc+proto"} }, message: HelloRequest { name: "ponytown client" } }
H2 Serve Error: Protocol(Error { kind: Io(Os { code: 10053, kind: ConnectionAborted, message: "An established connection was aborted by the software in your host machine." }) })

This is using stable-x86_64-pc-windows-msvc with rust 1.32.

@ian-p-cooke
Copy link
Author

ian-p-cooke commented Feb 14, 2019

I went back to my project (not the example above) and tested debug vs release and found the same result: a debug server with any client connecting via TlsStream<TcpStream, ClientSession> ends with a Protocol error. Replacing the client's TlsStream with my GracefulTlsStream in the client results in a debug server that does not report an error. If the server is in release mode then neither stream results in an error.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants