The existing APIs for spawning processes took strings for the command
and arguments, but the underlying system may not impose utf8 encoding,
so this is overly limiting.
The assumption we actually want to make is just that the command and
arguments are viewable as [u8] slices with no interior NULLs, i.e., as
CStrings. The ToCStr trait is a handy bound for types that meet this
requirement (such as &str and Path).
However, since the commands and arguments are often a mixture of
strings and paths, it would be inconvenient to take a slice with a
single T: ToCStr bound. So this patch revamps the process creation API
to instead use a builder-style interface, called `Command`, allowing
arguments to be added one at a time with differing ToCStr
implementations for each.
The initial cut of the builder API has some drawbacks that can be
addressed once issue #13851 (libstd as a facade) is closed. These are
detailed as FIXMEs.
Closes#11650.
[breaking-change]
This implements set_timeout() for std::io::Process which will affect wait()
operations on the process. This follows the same pattern as the rest of the
timeouts emerging in std::io::net.
The implementation was super easy for everything except libnative on unix
(backwards from usual!), which required a good bit of signal handling. There's a
doc comment explaining the strategy in libnative. Internally, this also required
refactoring the "helper thread" implementation used by libnative to allow for an
extra helper thread (not just the timer).
This is a breaking change in terms of the io::Process API. It is now possible
for wait() to fail, and subsequently wait_with_output(). These two functions now
return IoResult<T> due to the fact that they can time out.
Additionally, the wait_with_output() function has moved from taking `&mut self`
to taking `self`. If a timeout occurs while waiting with output, the semantics
are undesirable in almost all cases if attempting to re-wait on the process.
Equivalent functionality can still be achieved by dealing with the output
handles manually.
[breaking-change]
cc #13523
This moves as much allocation as possible from teh std::str module into
core::str. This includes essentially all non-allocating functionality, mostly
iterators and slicing and such.
This primarily splits the Str trait into only having the as_slice() method,
adding a new StrAllocating trait to std::str which contains the relevant new
allocation methods. This is a breaking change if any of the methods of "trait
Str" were overriden. The old functionality can be restored by implementing both
the Str and StrAllocating traits.
[breaking-change]
for `~str`/`~[]`.
Note that `~self` still remains, since I forgot to add support for
`Box<self>` before the snapshot.
How to update your code:
* Instead of `~EXPR`, you should write `box EXPR`.
* Instead of `~TYPE`, you should write `Box<Type>`.
* Instead of `~PATTERN`, you should write `box PATTERN`.
[breaking-change]
This removes all resizability support for ~[T] vectors in preparation of DST.
The only growable vector remaining is Vec<T>. In summary, the following methods
from ~[T] and various functions were removed. Each method/function has an
equivalent on the Vec type in std::vec unless otherwise stated.
* slice::OwnedCloneableVector
* slice::OwnedEqVector
* slice::append
* slice::append_one
* slice::build (no replacement)
* slice::bytes::push_bytes
* slice::from_elem
* slice::from_fn
* slice::with_capacity
* ~[T].capacity()
* ~[T].clear()
* ~[T].dedup()
* ~[T].extend()
* ~[T].grow()
* ~[T].grow_fn()
* ~[T].grow_set()
* ~[T].insert()
* ~[T].pop()
* ~[T].push()
* ~[T].push_all()
* ~[T].push_all_move()
* ~[T].remove()
* ~[T].reserve()
* ~[T].reserve_additional()
* ~[T].reserve_exect()
* ~[T].retain()
* ~[T].set_len()
* ~[T].shift()
* ~[T].shrink_to_fit()
* ~[T].swap_remove()
* ~[T].truncate()
* ~[T].unshift()
* ~str.clear()
* ~str.set_len()
* ~str.truncate()
Note that no other API changes were made. Existing apis that took or returned
~[T] continue to do so.
[breaking-change]
It turns out that on linux, and possibly other platforms, child processes will
continue to accept signals until they have been *reaped*. This means that once
the child has exited, it will succeed to receive signals until waitpid() has
been invoked on it.
This is unfortunate behavior, and differs from what is seen on OSX and windows.
This commit changes the behavior of Process::signal() to be the same across
platforms, and updates the documentation of Process::kill() to note that when
signaling a foreign process it may accept signals until reaped.
Implementation-wise, this invokes waitpid() with WNOHANG before each signal to
the child to ensure that if the child has exited that we will reap it. Other
possibilities include installing a SIGCHLD signal handler, but at this time I
believe that that's too complicated.
Closes#13124
Turns out the `timeout` command was exiting immediately because it didn't like
its output piped. Instead use `ping` repeatedly to get a process that will sleep
for awhile.
cc #12516
These two tests are notoriously flaky on the windows bots right now, so I'm
ignoring them until I can investigate them some more. The truncate_works test
has been flaky for quite some time, but it has gotten much worse recently. The
test_exists test has been flaky since the recent std::run rewrite landed.
Finally, the "unix pipe" test failure is a recent discovery on the try bots. I
haven't seen this failing much, but better safe than sorry!
cc #12516
The std::run module is a relic from a standard library long since past, and
there's not much use to having two modules to execute processes with where one
is slightly more convenient. This commit merges the two modules, moving lots of
functionality from std::run into std::io::process and then deleting
std::run.
New things you can find in std::io::process are:
* Process::new() now only takes prog/args
* Process::configure() takes a ProcessConfig
* Process::status() is the same as run::process_status
* Process::output() is the same as run::process_output
* I/O for spawned tasks is now defaulted to captured in pipes instead of ignored
* Process::kill() was added (plus an associated green/native implementation)
* Process::wait_with_output() is the same as the old finish_with_output()
* destroy() is now signal_exit()
* force_destroy() is now signal_kill()
Closes#2625Closes#10016
* All I/O now returns IoResult<T> = Result<T, IoError>
* All formatting traits now return fmt::Result = IoResult<()>
* The if_ok!() macro was added to libstd
Major changes:
- Define temporary scopes in a syntax-based way that basically defaults
to the innermost statement or conditional block, except for in
a `let` initializer, where we default to the innermost block. Rules
are documented in the code, but not in the manual (yet).
See new test run-pass/cleanup-value-scopes.rs for examples.
- Refactors Datum to better define cleanup roles.
- Refactor cleanup scopes to not be tied to basic blocks, permitting
us to have a very large number of scopes (one per AST node).
- Introduce nascent documentation in trans/doc.rs covering datums and
cleanup in a more comprehensive way.
Move the tests into libstd, use the `iotest!` macro to test both native and uv
bindings, and use the cloexec trick to figure out when the child process fails
in exec.
It is not the case that all programs will always be able to acquire an instance
of the LocalIo borrow, so this commit exposes this limitation by returning
Option<LocalIo> from LocalIo::borrow().
At the same time, a helper method LocalIo::maybe_raise() has been added in order
to encapsulate the functionality of raising on io_error if there is on local I/O
available.