Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 08166b5

Browse files
committedMar 14, 2025
feat(linker): check ARG_MAX on Unix platforms
On Unix the limits can be gargantuan anyway so we're pretty unlikely to hit them, but might still exceed it. We consult ARG_MAX here to get an estimate.
1 parent a672448 commit 08166b5

File tree

1 file changed

+41
-7
lines changed

1 file changed

+41
-7
lines changed
 

‎compiler/rustc_codegen_ssa/src/back/command.rs

+41-7
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,42 @@ impl Command {
137137
/// Returns a `true` if we're pretty sure that this'll blow OS spawn limits,
138138
/// or `false` if we should attempt to spawn and see what the OS says.
139139
pub(crate) fn very_likely_to_exceed_some_spawn_limit(&self) -> bool {
140-
// We mostly only care about Windows in this method, on Unix the limits
141-
// can be gargantuan anyway so we're pretty unlikely to hit them
142-
if cfg!(not(windows)) {
140+
#[cfg(not(any(windows, unix)))]
141+
{
143142
return false;
144143
}
145144

145+
// On Unix the limits can be gargantuan anyway so we're pretty
146+
// unlikely to hit them, but might still exceed it.
147+
// We consult ARG_MAX here to get an estimate.
148+
#[cfg(unix)]
149+
{
150+
let ptr_size = mem::size_of::<usize>();
151+
// arg + \0 + pointer
152+
let args_size = self.args.iter().fold(0usize, |acc, a| {
153+
let arg = a.as_encoded_bytes().len();
154+
let nul = 1;
155+
acc.saturating_add(arg).saturating_add(nul).saturating_add(ptr_size)
156+
});
157+
// key + `=` + value + \0 + pointer
158+
let envs_size = self.env.iter().fold(0usize, |acc, (k, v)| {
159+
let k = k.as_encoded_bytes().len();
160+
let eq = 1;
161+
let v = v.as_encoded_bytes().len();
162+
let nul = 1;
163+
acc.saturating_add(k)
164+
.saturating_add(eq)
165+
.saturating_add(v)
166+
.saturating_add(nul)
167+
.saturating_add(ptr_size)
168+
});
169+
let arg_max = match unsafe { libc::sysconf(libc::_SC_ARG_MAX) } {
170+
-1 => return false, // Go to OS anyway.
171+
max => max as usize,
172+
};
173+
return args_size.saturating_add(envs_size) > arg_max;
174+
}
175+
146176
// Ok so on Windows to spawn a process is 32,768 characters in its
147177
// command line [1]. Unfortunately we don't actually have access to that
148178
// as it's calculated just before spawning. Instead we perform a
@@ -165,10 +195,14 @@ impl Command {
165195
//
166196
// [1]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
167197
// [2]: https://devblogs.microsoft.com/oldnewthing/?p=41553
168-
169-
let estimated_command_line_len =
170-
self.args.iter().fold(0usize, |acc, a| acc.saturating_add(a.as_encoded_bytes().len()));
171-
estimated_command_line_len > 1024 * 6
198+
#[cfg(windows)]
199+
{
200+
let estimated_command_line_len = self
201+
.args
202+
.iter()
203+
.fold(0usize, |acc, a| acc.saturating_add(a.as_encoded_bytes().len()));
204+
return estimated_command_line_len > 1024 * 6;
205+
}
172206
}
173207
}
174208

0 commit comments

Comments
 (0)
Failed to load comments.