diff --git a/src/error.rs b/src/error.rs index 8b3fe74..e63fc7f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -18,6 +18,10 @@ pub enum FromEnvErrorKind { /// There is no jobserver in the environment variable. /// Variables associated with Make can be used for passing data other than jobserver info. NoJobserver, + /// POSIX jobserver allows passing negative file descriptors to notify that + /// jobserver is disabled for this process + /// (See ["GNU male manual: POSIX Jobserver Interaction"](https://www.gnu.org/software/make/manual/make.html#POSIX-Jobserver)). + NegativeFd, /// Cannot parse jobserver environment variable value, incorrect format. CannotParse, /// Cannot open path or name from the jobserver environment variable value. @@ -36,6 +40,7 @@ impl FromEnvError { match self.inner { FromEnvErrorInner::NoEnvVar => FromEnvErrorKind::NoEnvVar, FromEnvErrorInner::NoJobserver => FromEnvErrorKind::NoJobserver, + FromEnvErrorInner::NegativeFd(..) => FromEnvErrorKind::NegativeFd, FromEnvErrorInner::CannotParse(_) => FromEnvErrorKind::CannotParse, FromEnvErrorInner::CannotOpenPath(..) => FromEnvErrorKind::CannotOpenPath, FromEnvErrorInner::CannotOpenFd(..) => FromEnvErrorKind::CannotOpenFd, @@ -50,6 +55,7 @@ impl std::fmt::Display for FromEnvError { match &self.inner { FromEnvErrorInner::NoEnvVar => write!(f, "there is no environment variable that describes jobserver to inherit"), FromEnvErrorInner::NoJobserver => write!(f, "there is no `--jobserver-fds=` or `--jobserver-auth=` in the environment variable"), + FromEnvErrorInner::NegativeFd(read, write) => write!(f, "either or both passed file descriptors are negative: {read}, {write}"), 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}"), @@ -76,6 +82,7 @@ impl std::error::Error for FromEnvError { pub(crate) enum FromEnvErrorInner { NoEnvVar, NoJobserver, + NegativeFd(RawFd, RawFd), CannotParse(String), CannotOpenPath(String, std::io::Error), CannotOpenFd(RawFd, std::io::Error), diff --git a/src/unix.rs b/src/unix.rs index ee1e923..76bd283 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -130,6 +130,12 @@ 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 || write < 0 { + return Err(FromEnvErrorInner::NegativeFd(read, 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