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

async client stream does not know when a connection closes #136

Open
alex-shapiro opened this issue Jun 29, 2017 · 7 comments
Open

async client stream does not know when a connection closes #136

alex-shapiro opened this issue Jun 29, 2017 · 7 comments

Comments

@alex-shapiro
Copy link

alex-shapiro commented Jun 29, 2017

Problem: When a connection closes abnormally, the client stream does not return or acknowledge the broken connection.

Desired Behavior: When a connection closes abnormally, the client stream resolves immediately.

Quick demo of the problem, using the async-client + async-server examples:

  1. start the server
  2. start the client (and it connects to the server)
  3. kill the server with ctrl-C

The client stream remains open and shows no sign that the connection has closed. If the user sends a message via stdin_ch, the client accepts the message. If you send a second message, the client finally panics with a Broken Pipe IO error.

@alex-shapiro
Copy link
Author

It looks like the problem may be a more fundamental Tokio issue: tokio-rs/tokio-core#192

@illegalprime
Copy link
Collaborator

this is very strange, the async stuff is just a wrapper around a raw TcpStream, I'll try it out with two raw async TcpStreams and see if I can reproduce it.

@alex-shapiro
Copy link
Author

alex-shapiro commented Jul 26, 2017

I solved the problem. The issue is in the async-client example, not in the websocket crate itself.

The example uses select to combine two streams: incoming websocket messages and incoming channel messages. When the websocket connection closes, the stream of incoming websocket messages resolves.

However, the select future is essentially an "or" future - it doesn't resolve until both streams resolve. Since the channel receiver stream hasn't resolved, it continues sending messages to the websocket sink. Since the connection is closed, the sink will start rejecting messages.

I fixed the problem by replacing the built-in select with my own combinator, and_select, which resolves as soon as one of the streams resolves. So as soon as the websocket connection closes, the client closes. Here's the gist: https://gist.github.com/alex-shapiro/ab398f5a6a59ebf182b50fd50790d375

@illegalprime
Copy link
Collaborator

@alex-shapiro thanks for the fix, I'm re-opening so I can fix the example. I think it could be fixed without a new combinator and selecting over channel messages and results of polling the websocket

@illegalprime illegalprime reopened this Aug 7, 2017
@XiangQingW
Copy link

@illegalprime I meet the same issue when tcp is closed by peer. There is a way to reproduce this issue:

  1. cargo run --example async-client
  2. cargo run --example async-server
  3. exit the async-server by C-c, and the async-client doesn't know this closed status until I send a message in the terminal.

Have any idea to handle this issue? Thank you very much.

@vi
Copy link
Member

vi commented Dec 23, 2018

A non-websocket-related answer:

There's rather radical way: clone the underlying TCP socket and use the cloned sibling specifically for detecting connection reset.

Relevant Tokio issue: tokio-rs/tokio#483

@XiangQingW
Copy link

XiangQingW commented Dec 25, 2018

Thanks for reply. This is an amazing progress, however I can't get TcpStream in websocket-async-client.

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

No branches or pull requests

4 participants