diff --git a/src/error.rs b/src/error.rs index f3baaf0..10edb2e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -32,8 +32,8 @@ pub enum FromEnvErrorKind { /// is negative, which means it is disabled for this process /// ([GNU `make` manual: POSIX Jobserver Interaction](https://www.gnu.org/software/make/manual/make.html#POSIX-Jobserver)). NegativeFd, - /// File descriptor from the jobserver environment variable value is not a pipe. - NotAPipe, + /// File descriptor from the jobserver environment variable value is not a pipe or socket. + NotAPipeOrSocket, /// Jobserver inheritance is not supported on this platform. Unsupported, } @@ -48,7 +48,7 @@ impl FromEnvError { FromEnvErrorInner::CannotOpenPath(..) => FromEnvErrorKind::CannotOpenPath, FromEnvErrorInner::CannotOpenFd(..) => FromEnvErrorKind::CannotOpenFd, FromEnvErrorInner::NegativeFd(..) => FromEnvErrorKind::NegativeFd, - FromEnvErrorInner::NotAPipe(..) => FromEnvErrorKind::NotAPipe, + FromEnvErrorInner::NotAPipeOrSocket(..) => FromEnvErrorKind::NotAPipeOrSocket, FromEnvErrorInner::Unsupported => FromEnvErrorKind::Unsupported, } } @@ -63,8 +63,8 @@ impl std::fmt::Display for FromEnvError { FromEnvErrorInner::CannotOpenPath(s, err) => write!(f, "cannot open path or name {s} from the jobserver environment variable value: {err}"), FromEnvErrorInner::CannotOpenFd(fd, err) => write!(f, "cannot open file descriptor {fd} from the jobserver environment variable value: {err}"), FromEnvErrorInner::NegativeFd(fd) => write!(f, "file descriptor {fd} from the jobserver environment variable value is negative"), - FromEnvErrorInner::NotAPipe(fd, None) => write!(f, "file descriptor {fd} from the jobserver environment variable value is not a pipe"), - FromEnvErrorInner::NotAPipe(fd, Some(err)) => write!(f, "file descriptor {fd} from the jobserver environment variable value is not a pipe: {err}"), + FromEnvErrorInner::NotAPipeOrSocket(fd, None) => write!(f, "file descriptor {fd} from the jobserver environment variable value is not a pipe or socket"), + FromEnvErrorInner::NotAPipeOrSocket(fd, Some(err)) => write!(f, "file descriptor {fd} from the jobserver environment variable value is not a pipe or socket: {err}"), FromEnvErrorInner::Unsupported => write!(f, "jobserver inheritance is not supported on this platform"), } } @@ -73,9 +73,8 @@ impl std::error::Error for FromEnvError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match &self.inner { FromEnvErrorInner::CannotOpenPath(_, err) => Some(err), - FromEnvErrorInner::NotAPipe(_, Some(err)) | FromEnvErrorInner::CannotOpenFd(_, err) => { - Some(err) - } + FromEnvErrorInner::NotAPipeOrSocket(_, Some(err)) + | FromEnvErrorInner::CannotOpenFd(_, err) => Some(err), _ => None, } } @@ -90,6 +89,6 @@ pub(crate) enum FromEnvErrorInner { CannotOpenPath(String, std::io::Error), CannotOpenFd(RawFd, std::io::Error), NegativeFd(RawFd), - NotAPipe(RawFd, Option), + NotAPipeOrSocket(RawFd, Option), Unsupported, } diff --git a/src/unix.rs b/src/unix.rs index 2758e31..7b9c804 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -165,10 +165,10 @@ impl Client { // then we'll have `MAKEFLAGS` env vars but won't actually have // access to the file descriptors. // - // `NotAPipe` is a worse error, return it if it's reported for any of the two fds. + // `NotAPipeOrSocket` is a worse error, return it if it's reported for any of the two fds. match (fd_check(read, check_pipe), fd_check(write, check_pipe)) { - (read_err @ Err(FromEnvErrorInner::NotAPipe(..)), _) => read_err?, - (_, write_err @ Err(FromEnvErrorInner::NotAPipe(..))) => write_err?, + (read_err @ Err(FromEnvErrorInner::NotAPipeOrSocket(..)), _) => read_err?, + (_, write_err @ Err(FromEnvErrorInner::NotAPipeOrSocket(..))) => write_err?, (read_err, write_err) => { read_err?; write_err?; @@ -483,7 +483,7 @@ unsafe fn fd_check(fd: c_int, check_pipe: bool) -> Result<(), FromEnvErrorInner> if libc::fstat(fd, &mut stat) == -1 { let last_os_error = io::Error::last_os_error(); fcntl_check(fd)?; - Err(FromEnvErrorInner::NotAPipe(fd, Some(last_os_error))) + Err(FromEnvErrorInner::NotAPipeOrSocket(fd, Some(last_os_error))) } else { // On android arm and i686 mode_t is u16 and st_mode is u32, // this generates a type mismatch when S_IFIFO (declared as mode_t) @@ -495,7 +495,14 @@ unsafe fn fd_check(fd: c_int, check_pipe: bool) -> Result<(), FromEnvErrorInner> if stat.st_mode & s_ififo == s_ififo { return Ok(()); } - Err(FromEnvErrorInner::NotAPipe(fd, None)) + // Also allow sockets (S_IFSOCK) + #[allow(unused_assignments)] + let mut s_ifsock = stat.st_mode; + s_ifsock = libc::S_IFSOCK as _; + if stat.st_mode & s_ifsock == s_ifsock { + return Ok(()); + } + Err(FromEnvErrorInner::NotAPipeOrSocket(fd, None)) } } else { fcntl_check(fd)