std::process::Command and command-line length limits


#1

I’d like to create a subprocess with a lot of arguments. Every OS has some upper limit on how long the commandline can be. For my purposes, creating a process with X arguments, then creating a second process with the next Y arguments, then creating a third process with the next Z arguments etc. is an acceptable workaround. But I can’t see any obvious way to see if the next arg will push me over the limit. I can’t even see an OS-agnostic way to see if a given spawn call failed because the command-line was too long.

Am I missing something, or do I need to raise some feature-request/bug against std::process::Command? And in the meantime implement my own estimation of how long the command-line will be and track down some lowest-common-denominator limit across all OSs I can use as a hard-coded limit?


#2

If it’s truly target dependent and the current std::process::Command doesn’t follow that limit, I’d suggest raising a bug report. Similarly, you may want to look at filing a similar bug with std::env::args and std::env::args_os. Perhaps on those latter two it’s simply documenting, “a maximum of X args can be passed in” where X is dependent on the target.

How many arguments are you talking?


#3

As many as will fit. I’m looking to write some xargs like functionality


#4

Have you looked at how xargs itself does it? For instance, there’s xargs --show-limits, which gives this on Fedora 25:

Your environment variables take up 3723 bytes
POSIX upper limit on argument length (this system): 2091381
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2087658
Size of command buffer we are actually using: 131072
Maximum parallelism (--max-procs must be no greater): 2147483647

There’s also getconf ARG_MAX, using sysconf(_SC_ARG_MAX), which gives me 2097152.


#5

Oh I can work it out easily enough in linux-specific C. I might even be able to do it in rust with inside a bunch of [cfg] blocks. But I’d prefer to have the OS-specific bits abstracted away inside std::process:Command. If nothing elseI’d have to replicate all the knowledge of how the module generates the command-line, adds escaping characters, deals with more-than-2-bytes-long unicode char points etc.

I’ve raised https://github.com/rust-lang/rust/issues/40384