-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #113730 - belovdv:jobserver-init-check, r=petrochenkov
Report errors in jobserver inherited through environment variables This pr attempts to catch situations, when jobserver exists, but is not being inherited. r? `@petrochenkov`
- Loading branch information
Showing
10 changed files
with
114 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,78 @@ | ||
pub use jobserver_crate::Client; | ||
use std::sync::LazyLock; | ||
|
||
// We can only call `from_env` once per process | ||
|
||
// Note that this is unsafe because it may misinterpret file descriptors | ||
// on Unix as jobserver file descriptors. We hopefully execute this near | ||
// the beginning of the process though to ensure we don't get false | ||
// positives, or in other words we try to execute this before we open | ||
// any file descriptors ourselves. | ||
// | ||
// Pick a "reasonable maximum" if we don't otherwise have | ||
// a jobserver in our environment, capping out at 32 so we | ||
// don't take everything down by hogging the process run queue. | ||
// The fixed number is used to have deterministic compilation | ||
// across machines. | ||
// | ||
// Also note that we stick this in a global because there could be | ||
// multiple rustc instances in this process, and the jobserver is | ||
// per-process. | ||
static GLOBAL_CLIENT: LazyLock<Client> = LazyLock::new(|| unsafe { | ||
Client::from_env().unwrap_or_else(|| { | ||
let client = Client::new(32).expect("failed to create jobserver"); | ||
// Acquire a token for the main thread which we can release later | ||
client.acquire_raw().ok(); | ||
client | ||
}) | ||
|
||
use jobserver_crate::{FromEnv, FromEnvErrorKind}; | ||
|
||
use std::sync::{LazyLock, OnceLock}; | ||
|
||
// We can only call `from_env_ext` once per process | ||
|
||
// We stick this in a global because there could be multiple rustc instances | ||
// in this process, and the jobserver is per-process. | ||
static GLOBAL_CLIENT: LazyLock<Result<Client, String>> = LazyLock::new(|| { | ||
// Note that this is unsafe because it may misinterpret file descriptors | ||
// on Unix as jobserver file descriptors. We hopefully execute this near | ||
// the beginning of the process though to ensure we don't get false | ||
// positives, or in other words we try to execute this before we open | ||
// any file descriptors ourselves. | ||
let FromEnv { client, var } = unsafe { Client::from_env_ext(true) }; | ||
|
||
let error = match client { | ||
Ok(client) => return Ok(client), | ||
Err(e) => e, | ||
}; | ||
|
||
if matches!( | ||
error.kind(), | ||
FromEnvErrorKind::NoEnvVar | FromEnvErrorKind::NoJobserver | FromEnvErrorKind::Unsupported | ||
) { | ||
return Ok(default_client()); | ||
} | ||
|
||
// Environment specifies jobserver, but it looks incorrect. | ||
// Safety: `error.kind()` should be `NoEnvVar` if `var == None`. | ||
let (name, value) = var.unwrap(); | ||
Err(format!( | ||
"failed to connect to jobserver from environment variable `{name}={:?}`: {error}", | ||
value | ||
)) | ||
}); | ||
|
||
// Create a new jobserver if there's no inherited one. | ||
fn default_client() -> Client { | ||
// Pick a "reasonable maximum" capping out at 32 | ||
// so we don't take everything down by hogging the process run queue. | ||
// The fixed number is used to have deterministic compilation across machines. | ||
let client = Client::new(32).expect("failed to create jobserver"); | ||
|
||
// Acquire a token for the main thread which we can release later | ||
client.acquire_raw().ok(); | ||
|
||
client | ||
} | ||
|
||
static GLOBAL_CLIENT_CHECKED: OnceLock<Client> = OnceLock::new(); | ||
|
||
pub fn check(report_warning: impl FnOnce(&'static str)) { | ||
let client_checked = match &*GLOBAL_CLIENT { | ||
Ok(client) => client.clone(), | ||
Err(e) => { | ||
report_warning(e); | ||
default_client() | ||
} | ||
}; | ||
GLOBAL_CLIENT_CHECKED.set(client_checked).ok(); | ||
} | ||
|
||
const ACCESS_ERROR: &str = "jobserver check should have been called earlier"; | ||
|
||
pub fn client() -> Client { | ||
GLOBAL_CLIENT.clone() | ||
GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).clone() | ||
} | ||
|
||
pub fn acquire_thread() { | ||
GLOBAL_CLIENT.acquire_raw().ok(); | ||
GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).acquire_raw().ok(); | ||
} | ||
|
||
pub fn release_thread() { | ||
GLOBAL_CLIENT.release_raw().ok(); | ||
GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).release_raw().ok(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,15 @@ | ||
include ../tools.mk | ||
|
||
# only-linux | ||
# ignore-test: This test randomly fails, see https://github.com/rust-lang/rust/issues/110321 | ||
# ignore-cross-compile | ||
|
||
# Test compiler behavior in case: `jobserver-auth` points to correct pipe which is not jobserver. | ||
# Test compiler behavior in case environment specifies wrong jobserver. | ||
|
||
all: | ||
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff jobserver.stderr - | ||
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr - | ||
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff not_a_pipe.stderr - | ||
|
||
# This test randomly fails, see https://github.com/rust-lang/rust/issues/110321 | ||
disabled: | ||
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3< <(cat /dev/null)' 2>&1 | diff poisoned_pipe.stderr - | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,3"`: cannot open file descriptor 3 from the jobserver environment variable value: Bad file descriptor (os error 9) | ||
| | ||
= note: the build environment is likely misconfigured | ||
|
||
error: no input filename given | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,3"`: file descriptor 3 from the jobserver environment variable value is not a pipe | ||
| | ||
= note: the build environment is likely misconfigured | ||
|
File renamed without changes.