diff --git a/src/error.rs b/src/error.rs index 8b3fe74..eafb3c1 100644 --- a/src/error.rs +++ b/src/error.rs @@ -24,6 +24,10 @@ pub enum FromEnvErrorKind { CannotOpenPath, /// Cannot open file descriptor from the jobserver environment variable value. CannotOpenFd, + /// The jobserver style is a simple pipe, but at least one of the file descriptors + /// 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, /// Jobserver inheritance is not supported on this platform. @@ -39,6 +43,7 @@ impl FromEnvError { FromEnvErrorInner::CannotParse(_) => FromEnvErrorKind::CannotParse, FromEnvErrorInner::CannotOpenPath(..) => FromEnvErrorKind::CannotOpenPath, FromEnvErrorInner::CannotOpenFd(..) => FromEnvErrorKind::CannotOpenFd, + FromEnvErrorInner::NegativeFd(..) => FromEnvErrorKind::NegativeFd, FromEnvErrorInner::NotAPipe(..) => FromEnvErrorKind::NotAPipe, FromEnvErrorInner::Unsupported => FromEnvErrorKind::Unsupported, } @@ -53,6 +58,7 @@ impl std::fmt::Display for FromEnvError { FromEnvErrorInner::CannotParse(s) => write!(f, "cannot parse jobserver environment variable value: {s}"), 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::Unsupported => write!(f, "jobserver inheritance is not supported on this platform"), @@ -79,6 +85,7 @@ pub(crate) enum FromEnvErrorInner { CannotParse(String), CannotOpenPath(String, std::io::Error), CannotOpenFd(RawFd, std::io::Error), + NegativeFd(RawFd), NotAPipe(RawFd, Option), Unsupported, } diff --git a/src/unix.rs b/src/unix.rs index ee1e923..12cbe05 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -130,6 +130,15 @@ impl Client { .parse() .map_err(|e| FromEnvErrorInner::CannotParse(format!("cannot parse `write` fd: {e}")))?; + // If either or both of these file descriptors are negative, + // it means the jobserver is disabled for this process. + if read < 0 { + return Err(FromEnvErrorInner::NegativeFd(read)); + } + if write < 0 { + return Err(FromEnvErrorInner::NegativeFd(write)); + } + // Ok so we've got two integers that look like file descriptors, but // for extra sanity checking let's see if they actually look like // valid files and instances of a pipe if feature enabled before we