Skip to content

TcpStream::connect_timeout doesn't fail to connect to a nonexistent server on Linux #45265

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

Closed
sfackler opened this issue Oct 13, 2017 · 4 comments
Labels
O-linux Operating system: Linux T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@sfackler
Copy link
Member

use std::net::TcpStream;
use std::time::Duration;

fn main() {
    let sock = "127.0.0.1:1234".parse().unwrap();
    let timeout = Duration::from_secs(3);
    TcpStream::connect_timeout(&sock, timeout).unwrap();
}

This program succeeds on Linux, even though it shouldn't (assuming you don't have a listener on 1234). Trying to do anything with the socket produces Error { repr: Os { code: 107, message: "Transport endpoint is not connected" } }.

@sfackler
Copy link
Member Author

Interestingly it does behave as expected on macOS.

@sfackler sfackler added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Oct 13, 2017
@karizon
Copy link

karizon commented Oct 13, 2017

Works under WSL as well. Native linux it fails spectacularly.

@kennytm kennytm added the O-linux Operating system: Linux label Oct 13, 2017
@sfackler
Copy link
Member Author

From an strace, it looks like Linux sets all of POLLOUT, POLLERR, and POLLHUP at once. We treat POLLOUT as success, but it seems like we should be checking for POLLERR instead:

socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 3
ioctl(3, FIONBIO, [1])                  = 0
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
ioctl(3, FIONBIO, [0])                  = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=632431, tv_nsec=149012221}) = 0
clock_gettime(CLOCK_MONOTONIC, {tv_sec=632431, tv_nsec=149240049}) = 0
poll([{fd=3, events=POLLOUT}], 1, 2999) = 1 ([{fd=3, revents=POLLOUT|POLLERR|POLLHUP}])

@sfackler
Copy link
Member Author

Fix here: #45269

sfackler added a commit to sfackler/rust that referenced this issue Oct 14, 2017
Linux appears to set POLLOUT when a conection's refused, which is pretty
weird. Invert the check to look for an error explicitly. Also add an
explict test for this case.

Closes rust-lang#45265.
kennytm added a commit to kennytm/rust that referenced this issue Oct 14, 2017
…xcrichton

Fix TcpStream::connect_timeout on linux

Linux appears to set POLLOUT when a conection's refused, which is pretty
weird. Invert the check to look for an error explicitly. Also add an
explict test for this case.

Closes rust-lang#45265.

r? @alexcrichton
sfackler added a commit to sfackler/rust that referenced this issue Oct 14, 2017
Linux appears to set POLLOUT when a conection's refused, which is pretty
weird. Invert the check to look for an error explicitly. Also add an
explict test for this case.

Closes rust-lang#45265.
kennytm added a commit to kennytm/rust that referenced this issue Oct 15, 2017
…xcrichton

Fix TcpStream::connect_timeout on linux

Linux appears to set POLLOUT when a conection's refused, which is pretty
weird. Invert the check to look for an error explicitly. Also add an
explict test for this case.

Closes rust-lang#45265.

r? @alexcrichton
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-linux Operating system: Linux T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants