1 pub use jobserver_crate
::Client
;
3 use jobserver_crate
::{FromEnv, FromEnvErrorKind}
;
5 use std
::sync
::{LazyLock, OnceLock}
;
7 // We can only call `from_env_ext` once per process
9 // We stick this in a global because there could be multiple rustc instances
10 // in this process, and the jobserver is per-process.
11 static GLOBAL_CLIENT
: LazyLock
<Result
<Client
, String
>> = LazyLock
::new(|| {
12 // Note that this is unsafe because it may misinterpret file descriptors
13 // on Unix as jobserver file descriptors. We hopefully execute this near
14 // the beginning of the process though to ensure we don't get false
15 // positives, or in other words we try to execute this before we open
16 // any file descriptors ourselves.
17 let FromEnv { client, var }
= unsafe { Client::from_env_ext(true) }
;
19 let error
= match client
{
20 Ok(client
) => return Ok(client
),
26 FromEnvErrorKind
::NoEnvVar
| FromEnvErrorKind
::NoJobserver
| FromEnvErrorKind
::Unsupported
28 return Ok(default_client());
31 // Environment specifies jobserver, but it looks incorrect.
32 // Safety: `error.kind()` should be `NoEnvVar` if `var == None`.
33 let (name
, value
) = var
.unwrap();
35 "failed to connect to jobserver from environment variable `{name}={:?}`: {error}",
40 // Create a new jobserver if there's no inherited one.
41 fn default_client() -> Client
{
42 // Pick a "reasonable maximum" capping out at 32
43 // so we don't take everything down by hogging the process run queue.
44 // The fixed number is used to have deterministic compilation across machines.
45 let client
= Client
::new(32).expect("failed to create jobserver");
47 // Acquire a token for the main thread which we can release later
48 client
.acquire_raw().ok();
53 static GLOBAL_CLIENT_CHECKED
: OnceLock
<Client
> = OnceLock
::new();
55 pub fn initialize_checked(report_warning
: impl FnOnce(&'
static str)) {
56 let client_checked
= match &*GLOBAL_CLIENT
{
57 Ok(client
) => client
.clone(),
63 GLOBAL_CLIENT_CHECKED
.set(client_checked
).ok();
66 const ACCESS_ERROR
: &str = "jobserver check should have been called earlier";
68 pub fn client() -> Client
{
69 GLOBAL_CLIENT_CHECKED
.get().expect(ACCESS_ERROR
).clone()
72 pub fn acquire_thread() {
73 GLOBAL_CLIENT_CHECKED
.get().expect(ACCESS_ERROR
).acquire_raw().ok();
76 pub fn release_thread() {
77 GLOBAL_CLIENT_CHECKED
.get().expect(ACCESS_ERROR
).release_raw().ok();