summary refs log tree commit diff
path: root/library/std/src/sys/unix/process
AgeCommit message (Collapse)AuthorLines
2021-03-14Revert "Revert "use RWlock when accessing os::env #81850""The8472-3/+3
This reverts commit acdca316c3d42299d31c1b47eb792006ffdfc29c.
2021-03-10Rollup merge of #82949 - the8472:forget-envlock-on-fork, r=joshtriplettDylan DPC-6/+9
Do not attempt to unlock envlock in child process after a fork. This implements the first two points from https://github.com/rust-lang/rust/issues/64718#issuecomment-793030479 This is a breaking change for cases where the environment is accessed in a Command::pre_exec closure. Except for single-threaded programs these uses were not correct anyway since they aren't async-signal safe. Note that we had a ui test that explicitly tried `env::set_var` in `pre_exec`. As expected it failed with these changes when I tested locally.
2021-03-10Rollup merge of #82411 - ijackson:fix-exitstatus, r=dtolnayYuki Okushi-2/+45
Fixes to ExitStatus and its docs * On Unix, properly display every possible wait status (and don't panic on weird values) * In the documentation, be clear and consistent about "exit status" vs "wait status".
2021-03-09Do not attempt to unlock envlock in child process after a fork.The8472-6/+9
This is a breaking change for cases where the environment is accessed in a Command::pre_exec closure. Except for single-threaded programs these uses were not correct anyway since they aren't async-signal safe.
2021-03-09Always compile the fragile wait status test cases, just run them conditionallyIan Jackson-6/+7
Co-authored-by: David Tolnay <dtolnay@gmail.com>
2021-03-07Revert "use RWlock when accessing os::env #81850"Eric Huss-3/+3
This reverts commit 354f19cf2475148994954b6783341620c7445071, reversing changes made to 0cfba2fd090834c909d5ed9deccdee8170da791b.
2021-03-04ExitStatus tests: Make less legible to satisfy "tidy"Ian Jackson-2/+4
I strongly disagree with tidy in this case but AIUI there is no way to override it. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-03-04ExitStatus unknown wait status test: Make it Linux onlyIan Jackson-1/+1
If different unices have different bit patterns for WIFSTOPPED and WIFCONTINUED then simply being glibc is probably not good enough for this rather ad-hoc test to work. Do it on Linux only. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-03-04ExitStatus stop signal display test: Make it Linux onlyIan Jackson-2/+7
MacOS uses a different representation. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-02-23Update outdated comment in unix Command.Eric Huss-17/+5
2021-02-23process::unix: Test wait status formattingIan Jackson-0/+26
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-02-22process::unix: Handle other wait statuses in ExitStatus as DisplayIan Jackson-2/+11
Currently, on Nightly, this panics: ``` use std::process::ExitStatus; use std::os::unix::process::ExitStatusExt; fn main() { let st = ExitStatus::from_raw(0x007f); println!("st = {}", st); } ``` This is because the impl of Display assumes that if .code() is None, .signal() must be Some. That was a false assumption, although it was true with buggy code before 5b1316f78152a9c066b357ea9addf803d48e114a unix ExitStatus: Do not treat WIFSTOPPED as WIFSIGNALED This is not likely to have affected many people in practice, because `Command` will never produce such a wait status (`ExitStatus`). Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-02-08introduce StaticRWLock wrapper to make methods safeThe8472-3/+3
2021-02-07use rwlock for accessing ENVThe8472-3/+3
2021-01-21Add setgroups to std::os::unix::process::CommandExtslo1-7/+23
2021-01-20Deprecate-in-future the constants superceded by RFC 2700bstrie-1/+0
2021-01-17Don't use posix_spawn_file_actions_addchdir_np on macOS.Eric Huss-4/+14
2021-01-13Fix typos in Fuchsia unix_process_wait_moreDavid Tolnay-2/+2
2021-01-13ExitStatusExt: Fix build on FuchsiaIan Jackson-0/+44
This is not particularly pretty but the current situation is a mess and I don't think I'm making it significantly worse. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-01-13unix ExitStatus: Provide .continued()Ian Jackson-0/+4
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-01-13unix ExitStatus: Provide .stopped_signal()Ian Jackson-0/+4
Necessary to handle WIFSTOPPED. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-01-13unix ExitStatus: Provide .core_dumpedIan Jackson-0/+4
This is essential for proper reporting of child process status on Unix. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-01-13unix ExitStatus: Provide .into_raw()Ian Jackson-0/+4
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2021-01-13unix ExitStatus: Do not treat WIFSTOPPED as WIFSIGNALEDIan Jackson-1/+1
A unix wait status can contain, at least, exit statuses, termination signals, and stop signals. WTERMSIG is only valid if WIFSIGNALED. https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html It will not be easy to experience this bug with `Command`, because that doesn't pass WUNTRACED. But you could make an ExitStatus containing, say, a WIFSTOPPED, from a call to one of the libc wait functions. (In the WIFSTOPPED case, there is WSTOPSIG. But a stop signal is encoded differently to a termination signal, so WTERMSIG and WSTOPSIG are by no means the same.) Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2020-11-08Avoid overlapping cfg attributes when both macOS and aarch64Jake Goulding-10/+15
2020-10-20Check that pthread mutex initialization succeededTomasz Miąsko-5/+1
If pthread mutex initialization fails, the failure will go unnoticed unless debug assertions are enabled. Any subsequent use of mutex will also silently fail, since return values from lock & unlock operations are similarly checked only through debug assertions. In some implementations the mutex initialization requires a memory allocation and so it does fail in practice. Check that initialization succeeds to ensure that mutex guarantees mutual exclusion.
2020-10-17Auto merge of #77455 - asm89:faster-spawn, r=kennytmbors-1/+7
Use posix_spawn() on unix if program is a path Previously `Command::spawn` would fall back to the non-posix_spawn based implementation if the `PATH` environment variable was possibly changed. On systems with a modern (g)libc `posix_spawn()` can be significantly faster. If program is a path itself the `PATH` environment variable is not used for the lookup and it should be safe to use the `posix_spawnp()` method. [1] We found this, because we have a cli application that effectively runs a lot of subprocesses. It would sometimes noticeably hang while printing output. Profiling showed that the process was spending the majority of time in the kernel's `copy_page_range` function while spawning subprocesses. During this time the process is completely blocked from running, explaining why users were reporting the cli app hanging. Through this we discovered that `std::process::Command` has a fast and slow path for process execution. The fast path is backed by `posix_spawnp()` and the slow path by fork/exec syscalls being called explicitly. Using fork for process creation is supposed to be fast, but it slows down as your process uses more memory. It's not because the kernel copies the actual memory from the parent, but it does need to copy the references to it (see `copy_page_range` above!). We ended up using the slow path, because the command spawn implementation in falls back to the slow path if it suspects the PATH environment variable was changed. Here is a smallish program demonstrating the slowdown before this code change: ``` use std::process::Command; use std::time::Instant; fn main() { let mut args = std::env::args().skip(1); if let Some(size) = args.next() { // Allocate some memory let _xs: Vec<_> = std::iter::repeat(0) .take(size.parse().expect("valid number")) .collect(); let mut command = Command::new("/bin/sh"); command .arg("-c") .arg("echo hello"); if args.next().is_some() { println!("Overriding PATH"); command.env("PATH", std::env::var("PATH").expect("PATH env var")); } let now = Instant::now(); let child = command .spawn() .expect("failed to execute process"); println!("Spawn took: {:?}", now.elapsed()); let output = child.wait_with_output().expect("failed to wait on process"); println!("Output: {:?}", output); } else { eprintln!("Usage: prog [size]"); std::process::exit(1); } () } ``` Running it and passing different amounts of elements to use to allocate memory shows that the time taken for `spawn()` can differ quite significantly. In latter case the `posix_spawnp()` implementation is 30x faster: ``` $ cargo run --release 10000000 ... Spawn took: 324.275µs hello $ cargo run --release 10000000 changepath ... Overriding PATH Spawn took: 2.346809ms hello $ cargo run --release 100000000 ... Spawn took: 387.842µs hello $ cargo run --release 100000000 changepath ... Overriding PATH Spawn took: 13.434677ms hello ``` [1]: https://github.com/bminor/glibc/blob/5f72f9800b250410cad3abfeeb09469ef12b2438/posix/execvpe.c#L81
2020-10-16Take some of sys/vxworks/process/* from sys/unix instead.Mara Bos-1/+7
2020-10-08Check for errors returned from posix_spawn*_init functionsTomasz Miąsko-8/+10
The posix_spawnattr_init & posix_spawn_file_actions_init might fail, but their return code is not checked. Check for non-zero return code and destroy only succesfully initialized objects.
2020-10-08Check for non-zero return value from posix_spawn functionsTomasz Miąsko-10/+14
The cvt function compares the argument with -1 and when equal returns a new io::Error constructed from errno. It is used together posix_spawn_* functions. This is incorrect. Those functions do not set errno. Instead they return non-zero error code directly. Check for non-zero return code and use it to construct a new io::Error.
2020-10-04Update libc to 0.2.79Josh Triplett-23/+3
This also fixes issues with inconsistent `unsafe` on functions.
2020-10-02Rollup merge of #77432 - tmiasko:posix-spawn-musl, r=cuviperJonas Schievink-6/+8
Use posix_spawn on musl targets The posix_spawn had been available in a form suitable for use in a Command implementation since musl 0.9.12. Use it in a preference to a fork when possible, to benefit from CLONE_VM|CLONE_VFORK used there.
2020-10-02Use posix_spawn() on unix if program is a pathAlexander Mols-1/+7
Previously `Command::spawn` would fall back to the non-posix_spawn based implementation if the `PATH` environment variable was possibly changed. On systems with a modern (g)libc `posix_spawn()` can be significantly faster. If program is a path itself the `PATH` environment variable is not used for the lookup and it should be safe to use the `posix_spawnp()` method. [1] We found this, because we have a cli application that effectively runs a lot of subprocesses. It would sometimes noticeably hang while printing output. Profiling showed that the process was spending the majority of time in the kernel's `copy_page_range` function while spawning subprocesses. During this time the process is completely blocked from running, explaining why users were reporting the cli app hanging. Through this we discovered that `std::process::Command` has a fast and slow path for process execution. The fast path is backed by `posix_spawnp()` and the slow path by fork/exec syscalls being called explicitly. Using fork for process creation is supposed to be fast, but it slows down as your process uses more memory. It's not because the kernel copies the actual memory from the parent, but it does need to copy the references to it (see `copy_page_range` above!). We ended up using the slow path, because the command spawn implementation in falls back to the slow path if it suspects the PATH environment variable was changed. Here is a smallish program demonstrating the slowdown before this code change: ``` use std::process::Command; use std::time::Instant; fn main() { let mut args = std::env::args().skip(1); if let Some(size) = args.next() { // Allocate some memory let _xs: Vec<_> = std::iter::repeat(0) .take(size.parse().expect("valid number")) .collect(); let mut command = Command::new("/bin/sh"); command .arg("-c") .arg("echo hello"); if args.next().is_some() { println!("Overriding PATH"); command.env("PATH", std::env::var("PATH").expect("PATH env var")); } let now = Instant::now(); let child = command .spawn() .expect("failed to execute process"); println!("Spawn took: {:?}", now.elapsed()); let output = child.wait_with_output().expect("failed to wait on process"); println!("Output: {:?}", output); } else { eprintln!("Usage: prog [size]"); std::process::exit(1); } () } ``` Running it and passing different amounts of elements to use to allocate memory shows that the time taken for `spawn()` can differ quite significantly. In latter case the `posix_spawnp()` implementation is 30x faster: ``` $ cargo run --release 10000000 ... Spawn took: 324.275µs hello $ cargo run --release 10000000 changepath ... Overriding PATH Spawn took: 2.346809ms hello $ cargo run --release 100000000 ... Spawn took: 387.842µs hello $ cargo run --release 100000000 changepath ... Overriding PATH Spawn took: 13.434677ms hello ``` [1]: https://github.com/bminor/glibc/blob/5f72f9800b250410cad3abfeeb09469ef12b2438/posix/execvpe.c#L81
2020-10-02Auto merge of #77029 - ehuss:command-access, r=dtolnaybors-6/+56
Add accessors to Command. This adds some accessor methods to `Command` to provide a way to access the values set when building the `Command`. An example where this can be useful is to display the command to be executed. This is roughly based on the [`ProcessBuilder`](https://github.com/rust-lang/cargo/blob/13b73cdaf76b2d9182515c9cf26a8f68342d08ef/src/cargo/util/process_builder.rs#L105-L134) in Cargo. Possible concerns about the API: - Values with NULs on Unix will be returned as `"<string-with-nul>"`. I don't think it is practical to avoid this, since otherwise a whole separate copy of all the values would need to be kept in `Command`. - Does not handle `arg0` on Unix. This can be awkward to support in `get_args` and is rarely used. I figure if someone really wants it, it can be added to `CommandExt` as a separate method. - Does not offer a way to detect `env_clear`. I'm uncertain if it would be useful for anyone. - Does not offer a way to get an environment variable by name (`get_env`). I figure this can be added later if anyone really wants it. I think the motivation for this is weak, though. Also, the API could be a little awkward (return a `Option<Option<&OsStr>>`?). - `get_envs` could skip "cleared" entries and just return `&OsStr` values instead of `Option<&OsStr>`. I'm on the fence here. My use case is to display a shell command, and I only intend it to be roughly equivalent to the actual execution, and I probably won't display `None` entries. I erred on the side of providing extra information, but I suspect many situations will just filter out the `None`s. - Could implement more iterator stuff (like `DoubleEndedIterator`). I have not implemented new std items before, so I'm uncertain if the existing issue should be reused, or if a new tracking issue is needed. cc #44434
2020-10-01Use posix_spawn on musl targetsTomasz Miąsko-6/+8
The posix_spawn had been available in a form suitable for use in a Command implementation since musl 0.9.12. Use it in a preference to a fork when possible, to benefit from CLONE_VM|CLONE_VFORK used there.
2020-09-29Use `rtassert!` instead of `assert!` from the child process after fork() in ↵hyd-dev-1/+1
std::sys::unix::process::Command::spawn() `assert!` panics on failure, which is not signal-safe.
2020-09-26Add accessors to Command.Eric Huss-6/+56
2020-09-15[fuchsia] Propagate the userspace UTC clockAdam Lesinski-1/+3
On Fuchsia, spawning a subprocess does not automatically clone all of the parent process' capabilities. UTC time on Fuchsia is managed by a top-level userspace clock capability that is cloned and passed to subprocesses. This change ensures that any Rust subprocess gets access to the UTC clock, if the parent had access to it. This is critical for tests, which on Fuchsia, use panic=abort and spawn subprocesses per test.
2020-09-11Ignore unnecessary unsafe warningsThomas de Zeeuw-1/+21
This is a work-around for a libc issue: https://github.com/rust-lang/libc/issues/1888.
2020-08-31std: move "mod tests/benches" to separate filesLzu Tao-68/+67
Also doing fmt inplace as requested.
2020-07-27mv std libs to library/mark-0/+1543