From 493ca3364a48ad8cf68fde2056a99e2ac0095ec6 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Wed, 25 Jan 2023 11:52:40 +0000 Subject: [PATCH 1/2] Fix incorrect comment. The event loop uses poll(2), not select(2). --- crates/cargo-util/src/read2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cargo-util/src/read2.rs b/crates/cargo-util/src/read2.rs index 53322a51d70..0d4029052f7 100644 --- a/crates/cargo-util/src/read2.rs +++ b/crates/cargo-util/src/read2.rs @@ -32,7 +32,7 @@ mod imp { let mut errfd = 1; while nfds > 0 { - // wait for either pipe to become readable using `select` + // wait for either pipe to become readable using `poll` let r = unsafe { libc::poll(fds.as_mut_ptr(), nfds, -1) }; if r == -1 { let err = io::Error::last_os_error(); From 5c3825ffc56b7678157200088e70bec0fca2ed07 Mon Sep 17 00:00:00 2001 From: Edd Barrett Date: Wed, 25 Jan 2023 12:00:59 +0000 Subject: [PATCH 2/2] Set non-blocking IO more robustly. - Check for errors. - Add O_NONBLOCK on top of any existing flags. set_nonblock() is adapted from lang_tester: https://github.com/softdevteam/lang_tester/blob/e01072a0a4c5e37f2e585c48efffcf540cd7b6a4/src/tester.rs#L1041-L1048 --- crates/cargo-util/src/read2.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/cargo-util/src/read2.rs b/crates/cargo-util/src/read2.rs index 0d4029052f7..6aaed7eb40a 100644 --- a/crates/cargo-util/src/read2.rs +++ b/crates/cargo-util/src/read2.rs @@ -2,21 +2,28 @@ pub use self::imp::read2; #[cfg(unix)] mod imp { + use libc::{c_int, fcntl, F_GETFL, F_SETFL, O_NONBLOCK}; use std::io; use std::io::prelude::*; use std::mem; use std::os::unix::prelude::*; use std::process::{ChildStderr, ChildStdout}; + fn set_nonblock(fd: c_int) -> io::Result<()> { + let flags = unsafe { fcntl(fd, F_GETFL) }; + if flags == -1 || unsafe { fcntl(fd, F_SETFL, flags | O_NONBLOCK) } == -1 { + return Err(io::Error::last_os_error()); + } + Ok(()) + } + pub fn read2( mut out_pipe: ChildStdout, mut err_pipe: ChildStderr, data: &mut dyn FnMut(bool, &mut Vec, bool), ) -> io::Result<()> { - unsafe { - libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); - libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); - } + set_nonblock(out_pipe.as_raw_fd())?; + set_nonblock(err_pipe.as_raw_fd())?; let mut out_done = false; let mut err_done = false;