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

Use non-blocking connect for TcpStream. #687

Merged
2 commits merged into from
Jan 27, 2020
Merged

Conversation

twittner
Copy link
Contributor

@twittner twittner commented Jan 23, 2020

Instead of spawning a background thread which is unaware of any timeouts but continues to run until the TCP stack decides that the remote is not reachable we use mio's non-blocking connect.

mio's TcpStream::connect returns immediately but the actual connection is usually just in progress and we have to be sure the socket is writeable before we can consider the connection as established.

The Watcher and Reactor APIs have changed a bit to (a) allow registration together with an initial set of Wakers in order to avoid missing any wakeups that may occur before we even registered a Waker with Watcher::{poll_read_with, poll_write_with}, and (b) to allow registration with readiness interests other than PollOpt::all().

Update: Following a suggestion of @stjepang we offer methods to check for read/write readiness of a Watcher instead of the approach in the previous paragraph to accept a set of Wakers when registering an event source. The changes relative to master are smaller and both methods look more useful in other contexts. Also the code is more robust w.r.t. wakeups of the Waker from clones outside the Reactor.

I am not sure if we need to add protection mechanisms against spurious wakeups from mio. Currently we treat the Poll::Ready(()) from Watcher::poll_write_ready as proof that the non-blocking connect has finished, but if the event from mio was a spurious one, it might still be ongoing.

Context: #678.

Instead of spawning a background thread which is unaware of any timeouts
but continues to run until the TCP stack decides that the remote is not
reachable we use mio's non-blocking connect.

mio's `TcpStream::connect` returns immediately but the actual connection
is usually just in progress and we have to be sure the socket is
writeable before we can consider the connection as established.
Following a suggestion of @stjepang we offer methods to check for
read/write readiness of a `Watcher` instead of the previous approach to
accept a set of `Waker`s when registering an event source. The changes
relative to master are smaller and both methods look more useful in
other contexts. Also the code is more robust w.r.t. wakeups of the
`Waker` from clones outside the `Reactor`.

I am not sure if we need to add protection mechanisms against spurious
wakeups from mio. Currently we treat the `Poll::Ready(())` of
`Watcher::poll_write_ready` as proof that the non-blocking connect has
finished, but if the event from mio was a spurious one, it might still
be ongoing.
@yoshuawuyts yoshuawuyts requested a review from a user January 27, 2020 12:13
Copy link
Contributor

@yoshuawuyts yoshuawuyts left a comment

Choose a reason for hiding this comment

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

No objections to this patch, especially since CI passes and it fixes an actual bug. I'd love to have an extra test to prevent any regressions of the reported bug; but even without it that shouldn't block merging this patch.

Delegating to @stjepang for a full review though.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

This is perfect, thank you so much! :)

@ghost ghost merged commit 57974ae into async-rs:master Jan 27, 2020
@twittner twittner deleted the connect-with-mio branch January 28, 2020 09:21
@tomaka
Copy link

tomaka commented Jan 30, 2020

@yoshuawuyts @stjepang Would it be possible to release a version including this in the not-too-far future? (it doesn't need to be in the next hours/days, but not too far away either if possible)

In Polkadot we're sometimes reaching a limit to the number of threads using async-std 1.4 (possibly because we're within docker), which causes a panic in spawn_blocking. We did an "emergency" PR paritytech/polkadot#810 that uses async-std master which works fine.

@yoshuawuyts
Copy link
Contributor

@tomaka Ah yeah, for sure. Going to make some time next week to issue a new release.

This pull request was closed.
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

Successfully merging this pull request may close these issues.

3 participants