This commit, after reverting #55359, applies a different fix for #46775
while also fixing #55775. The basic idea was to go back to pre-#55359
libstd, and then fix#46775 in a way that doesn't expose #55775.
The issue described in #46775 boils down to two problems:
* First, the global environment is reset during `exec` but, but if the
`exec` call fails then the global environment was a dangling pointer
into free'd memory as the block of memory was deallocated when
`Command` is dropped. This is fixed in this commit by installing a
`Drop` stack object which ensures that the `environ` pointer is
preserved on a failing `exec`.
* Second, the global environment was accessed in an unsynchronized
fashion during `exec`. This was fixed by ensuring that the
Rust-specific environment lock is acquired for these system-level
operations.
Thanks to Alex Gaynor for pioneering the solution here!
Closes#55775
Co-authored-by: Alex Gaynor <alex.gaynor@gmail.com>
Instead, pass the environment to execvpe, so the kernel can apply it directly to the new process. This avoids a use-after-free in the case where exec'ing the new process fails for any reason, as well as a race condition if there are other threads alive during the exec.
These were showing up in tests and in binaries but are trivially optimize-able
away, so add `#[inline]` attributes so LLVM has an opportunity to optimize them
out.
The expected behavior is that the environment's PATH should be used
to find the process. posix_spawn() could be used if we iterated
PATH to search for the binary to execute. For now just skip
posix_spawn() if PATH is modified.
spawn() is expected to return an error if the specified file could not be
executed. FreeBSD's posix_spawn() supports returning ENOENT/ENOEXEC if
the exec() fails, which not all platforms support. This brings a very
significant performance improvement for FreeBSD, involving heavy use of
Command in threads, due to fork() invoking jemalloc fork handlers and
causing lock contention. FreeBSD's posix_spawn() avoids this problem
due to using vfork() internally.
Remove support for the PNaCl target (le32-unknown-nacl)
This removes support for the `le32-unknown-nacl` target which is currently supported by rustc on tier 3. Despite the "nacl" in the name, the target doesn't output native code (x86, ARM, MIPS), instead it outputs binaries in the PNaCl format.
There are two reasons for the removal:
* Google [has announced](https://blog.chromium.org/2017/05/goodbye-pnacl-hello-webassembly.html) deprecation of the PNaCl format. The suggestion is to migrate to wasm. Happens we already have a wasm backend!
* Our PNaCl LLVM backend is provided by the fastcomp patch set that the LLVM fork used by rustc contains in addition to vanilla LLVM (`src/llvm/lib/Target/JSBackend/NaCl`). Upstream LLVM doesn't have PNaCl support. Removing PNaCl support will enable us to move away from fastcomp (#44006) and have a lighter set of patches on top of upstream LLVM inside our LLVM fork. This will help distribution packagers of Rust.
Fixes#42420
* Use size_t where size_t is used, while it's not critical on our
specifically supported architectures, this is more accurate.
* Update HND_SPECIAL_COUNT to the correct value, and give it the size
that enum is likely to be.
* Match definition of c_char in os/raw.rs with the libc definition
Due to historic reasons, os/raw.rs redefines types for c_char from
libc, but these didn't match. Now they do :).
* Enable signal reset on exec for L4Re
L4Re has full signal emulation and hence it needs to reset the
signal set of the child with sigemptyset. However, gid and uid
should *not* be set.
This commit adds a disabled builder which will run all tests for the standard
library for aarch64 in a QEMU instance. Once we get enough capacity to run this
on Travis this can be used to boost our platform coverage of AArch64
`Stdio` now implements `From<ChildStdin>`, `From<ChildStdout>`,
`From<ChildStderr>`, and `From<File>`.
The `Command::stdin`/`stdout`/`stderr` methods now take any type that
implements `Into<Stdio>`.
This makes it much easier to write shell-like command chains, piping to
one another and redirecting to and from files. Otherwise one would need
to use the unsafe and OS-specific `from_raw_fd` or `from_raw_handle`.
The implementation of mx_job_default changed from a macro which
accessed the __magenta_job_default global variable to a proper
function call. This patch tracks that change.
The mx_handle_wait_* syscalls in Magenta were renamed to
mx_object_wait. The syscall is used in the Magenta/Fuchsia
implementation of std::process, to wait on child processes.
In addition, this patch enables the use of the system provided
libbacktrace library on Fuchsia targets. Symbolization is not yet
working, but at least it allows printing hex addresses in a backtrace
and makes building succeed when the backtrace feature is not disabled.
make Child::try_wait return io::Result<Option<ExitStatus>>
This is much nicer for callers who want to short-circuit real I/O errors
with `?`, because they can write this
if let Some(status) = foo.try_wait()? {
...
} else {
...
}
instead of this
match foo.try_wait() {
Ok(status) => {
...
}
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
...
}
Err(err) => return Err(err),
}
The original design of `try_wait` was patterned after the `Read` and
`Write` traits, which support both blocking and non-blocking
implementations in a single API. But since `try_wait` is never blocking,
it makes sense to optimize for the non-blocking case.
Tracking issue: https://github.com/rust-lang/rust/issues/38903
This is much nicer for callers who want to short-circuit real I/O errors
with `?`, because they can write this
if let Some(status) = foo.try_wait()? {
...
} else {
...
}
instead of this
match foo.try_wait() {
Ok(status) => {
...
}
Err(err) if err.kind() == io::ErrorKind::WouldBlock => {
...
}
Err(err) => return Err(err),
}
The original design of `try_wait` was patterned after the `Read` and
`Write` traits, which support both blocking and non-blocking
implementations in a single API. But since `try_wait` is never blocking,
it makes sense to optimize for the non-blocking case.
Tracking issue: https://github.com/rust-lang/rust/issues/38903
This commit adds support to the build system to execute test suites that cannot
run natively but can instead run inside of a QEMU emulator. A proof-of-concept
builder was added for the `arm-unknown-linux-gnueabihf` target to show off how
this might work.
In general the architecture is to have a server running inside of the emulator
which a local client connects to. The protocol between the server/client
supports compiling tests on the host and running them on the target inside the
emulator.
Closes#33114
This commit adds a new method to the `Child` type in the `std::process` module
called `try_wait`. This method is the same as `wait` except that it will not
block the calling thread and instead only attempt to collect the exit status. On
Unix this means that we call `waitpid` with the `WNOHANG` flag and on Windows it
just means that we pass a 0 timeout to `WaitForSingleObject`.
Currently it's possible to build this method out of tree, but it's unfortunately
tricky to do so. Specifically on Unix you essentially lose ownership of the pid
for the process once a call to `waitpid` has succeeded. Although `Child` tracks
this state internally to be resilient to multiple calls to `wait` or a `kill`
after a successful wait, if the child is waited on externally then the state
inside of `Child` is not updated. This means that external implementations of
this method must be extra careful to essentially not use a `Child`'s methods
after a call to `waitpid` has succeeded (even in a nonblocking fashion).
By adding this functionality to the standard library it should help canonicalize
these external implementations and ensure they can continue to robustly reuse
the `Child` type from the standard library without worrying about pid ownership.