Skip to content

Commit e668eb3

Browse files
committed
Make TCP connect handle EINTR correctly
According to the POSIX standard, if connect() is interrupted by a signal that is caught while blocked waiting to establish a connection, connect() shall fail and set errno to EINTR, but the connection request shall not be aborted, and the connection shall be established asynchronously. When the connection has been established asynchronously, select() and poll() shall indicate that the file descriptor for the socket is ready for writing. When we try to call connect() again, the connection can already be istablished asynchronously and we get EISCONN error. In this case we should not return error (as we previously did).
1 parent 42ca6e4 commit e668eb3

File tree

2 files changed

+12
-3
lines changed

2 files changed

+12
-3
lines changed

library/std/src/sys/unix/mod.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,18 @@ where
323323
F: FnMut() -> T,
324324
{
325325
loop {
326-
match cvt(f()) {
327-
Err(ref e) if e.is_interrupted() => {}
328-
other => return other,
326+
let t = f();
327+
if t.is_minus_one() {
328+
let e = crate::io::Error::last_os_error();
329+
if e.is_interrupted() {
330+
continue;
331+
}
332+
if e.raw_os_error() == Some(libc::EISCONN) {
333+
return Ok(t);
334+
}
335+
return Err(e);
329336
}
337+
return Ok(t);
330338
}
331339
}
332340

library/std/src/sys_common/net.rs

+1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ impl TcpStream {
229229

230230
let (addr, len) = addr.into_inner();
231231
cvt_r(|| unsafe { c::connect(sock.as_raw(), addr.as_ptr(), len) })?;
232+
sock.take_error()?;
232233
Ok(TcpStream { inner: sock })
233234
}
234235

0 commit comments

Comments
 (0)