Skip to content

Remove TcpStream::peer_addr check for network sockets, test epoll readiness for shutdown#5009

Open
WhySoBad wants to merge 3 commits intorust-lang:masterfrom
WhySoBad:network-socket-fix-shutdown
Open

Remove TcpStream::peer_addr check for network sockets, test epoll readiness for shutdown#5009
WhySoBad wants to merge 3 commits intorust-lang:masterfrom
WhySoBad:network-socket-fix-shutdown

Conversation

@WhySoBad
Copy link
Copy Markdown
Contributor

@WhySoBad WhySoBad commented May 8, 2026

As mentioned in #5005, this pull request fixes a bug with shutdown and non-blocking sockets. Additionally, it also adds tests for shutdown in combination with epoll.

The bug occurs when we connect a non-blocking socket and shut down the write end of the connecting socket before the socket became connected. As a consequence, the TcpStream::peer_addr call in the ensure_connected method fails because after closing the write end, we can no longer get the peer. Our current logic treats this failure as an OS error and panics.
Because tokio doesn't implement this suggested check with TcpStream::peer_addr and everything seems to work fine, we should also be fine with removing the check and by this resolving the panic.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 8, 2026

Thank you for contributing to Miri! A reviewer will take a look at your PR, typically within a week or two.
Please remember to not force-push to the PR branch except when you need to rebase due to a conflict or when the reviewer asks you for it.

@rustbot rustbot added the S-waiting-on-review Status: Waiting for a review to complete label May 8, 2026
Copy link
Copy Markdown
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

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

Comment thread src/shims/unix/socket.rs Outdated
Comment thread src/shims/unix/socket.rs
Comment thread src/shims/unix/socket.rs
Comment on lines +1136 to +1140
// Closing the read end of a socket causes an EPOLLRDHUP event.
readiness.read_closed |= is_read_shutdown || is_read_write_shutdown;
// Only shutting down the write end doesn't cause an EPOLLHUP event
// and thus we won't set the `write_closed` readiness for it here.
readiness.write_closed |= is_read_write_shutdown;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Have you confirmed that this matches what Linux does?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(and the tests also pass on my Linux host)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The kernel seems to also set EPOLLIN?

Comment thread src/shims/unix/socket.rs
Comment on lines +1131 to +1134
// Because we map cross platform mio readiness to epoll readiness and
// the different platforms don't treat `shutdown` the same way, we set
// the readiness after a `shutdown` manually to achieve more consistent
// epoll readiness.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What goes wrong (on which hosts) if we don't do this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

On Windows hosts the tests which only shut down the read/write end of the socket hang indefinitely otherwise.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// Because we map cross platform mio readiness to epoll readiness and
// the different platforms don't treat `shutdown` the same way, we set
// the readiness after a `shutdown` manually to achieve more consistent
// epoll readiness.
// Because we map cross platform mio readiness to epoll readiness and
// the different platforms don't treat `shutdown` the same way, we set
// the readiness after a `shutdown` manually to achieve more consistent
// epoll readiness. Otherwise we do not generate enough epoll events
// on partial shutdowns on Windows hosts.

Comment thread src/shims/unix/socket.rs Outdated
Comment thread src/shims/unix/socket.rs Outdated
@rustbot rustbot added S-waiting-on-author Status: Waiting for the PR author to address review comments and removed S-waiting-on-review Status: Waiting for a review to complete labels May 8, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented May 8, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

Copy link
Copy Markdown
Member

@RalfJung RalfJung May 8, 2026

Choose a reason for hiding this comment

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

The bug occurs when we connect a non-blocking socket and shut down the write end of the connecting socket before the socket became connected. As a consequence, the TcpStream::peer_addr call in the ensure_connected method fails because after closing the write end, we can no longer get the peer. Our current logic treats this failure as an OS error and panics.

Is it possible to add / extend a test to cover that case?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We cannot really test this because we need a socket which is stuck at connecting to a address + port and to which address + port we later bind a listener. Because we need to use randomized ports to avoid "address is already used" errors, we cannot know such a port before binding (listening to get a TcpListener).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We could pick something like 127.0.0.208:23754 that is unlikely to be used.

@WhySoBad
Copy link
Copy Markdown
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Waiting for a review to complete and removed S-waiting-on-author Status: Waiting for the PR author to address review comments labels May 10, 2026
Comment thread src/shims/unix/socket.rs
// [`TcpStream::take_err`] and [`TcpStream::peer_addr`] both
// don't return an error after receiving an [`Interest::WRITEABLE`]
// event on the stream.
// Mio does not wait until the stream is fully connected.
Copy link
Copy Markdown
Member

@RalfJung RalfJung May 11, 2026

Choose a reason for hiding this comment

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

On second thought, here's a better wording:

Suggested change
// Mio does not wait until the stream is fully connected.
// This begins establishing the connection, but does not block until the stream is fully connected.

View changes since the review

@RalfJung
Copy link
Copy Markdown
Member

@rustbot author

@rustbot rustbot added S-waiting-on-author Status: Waiting for the PR author to address review comments and removed S-waiting-on-review Status: Waiting for a review to complete labels May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: Waiting for the PR author to address review comments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants