@@ -137,12 +137,42 @@ impl Command {
137
137
/// Returns a `true` if we're pretty sure that this'll blow OS spawn limits,
138
138
/// or `false` if we should attempt to spawn and see what the OS says.
139
139
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 ! ( unix) {
140
+ #[ cfg( not( any( windows, unix) ) ) ]
141
+ {
143
142
return false ;
144
143
}
145
144
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
+
146
176
// Ok so on Windows to spawn a process is 32,768 characters in its
147
177
// command line [1]. Unfortunately we don't actually have access to that
148
178
// as it's calculated just before spawning. Instead we perform a
@@ -165,9 +195,14 @@ impl Command {
165
195
//
166
196
// [1]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
167
197
// [2]: https://devblogs.microsoft.com/oldnewthing/?p=41553
168
-
169
- let estimated_command_line_len = self . args . iter ( ) . map ( |a| a. len ( ) ) . sum :: < usize > ( ) ;
170
- 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
+ }
171
206
}
172
207
}
173
208
0 commit comments