summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2017-10-15 14:21:57 +0800
committerGitHub <noreply@github.com>2017-10-15 14:21:57 +0800
commitf55cb4856b0c5e3517e348102d18d9a23f20c0be (patch)
tree726d98b6b37b7c176f621be6995a4ae127acd8f4 /src/libstd
parenta793372d8ce0eb11abd211d335619889b9bbc6ac (diff)
parentcab99a3f8c8dcdfd9052fd54787d22611ab36edc (diff)
downloadrust-f55cb4856b0c5e3517e348102d18d9a23f20c0be.tar.gz
rust-f55cb4856b0c5e3517e348102d18d9a23f20c0be.zip
Rollup merge of #45269 - sfackler:connect-timeout-fix, r=alexcrichton
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 #45265.

r? @alexcrichton
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/net/tcp.rs15
-rw-r--r--src/libstd/sys/unix/net.rs13
2 files changed, 24 insertions, 4 deletions
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index b904641a336..4656cc5a7a7 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -1580,6 +1580,21 @@ mod tests {
     }
 
     #[test]
+    fn connect_timeout_unbound() {
+        // bind and drop a socket to track down a "probably unassigned" port
+        let socket = TcpListener::bind("127.0.0.1:0").unwrap();
+        let addr = socket.local_addr().unwrap();
+        drop(socket);
+
+        let timeout = Duration::from_secs(1);
+        let e = TcpStream::connect_timeout(&addr, timeout).unwrap_err();
+        assert!(e.kind() == io::ErrorKind::ConnectionRefused ||
+                e.kind() == io::ErrorKind::TimedOut ||
+                e.kind() == io::ErrorKind::Other,
+                "bad error: {} {:?}", e, e.kind());
+    }
+
+    #[test]
     fn connect_timeout_valid() {
         let listener = TcpListener::bind("127.0.0.1:0").unwrap();
         let addr = listener.local_addr().unwrap();
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index c8019d1c768..e775f857f2b 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -176,11 +176,16 @@ impl Socket {
                 }
                 0 => {}
                 _ => {
-                    if pollfd.revents & libc::POLLOUT == 0 {
-                        if let Some(e) = self.take_error()? {
-                            return Err(e);
-                        }
+                    // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
+                    // for POLLHUP rather than read readiness
+                    if pollfd.revents & libc::POLLHUP != 0 {
+                        let e = self.take_error()?
+                            .unwrap_or_else(|| {
+                                io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
+                            });
+                        return Err(e);
                     }
+
                     return Ok(());
                 }
             }