-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
non-Unix cfg(unix)
ExitStatus
is broken
#114593
Comments
Ugh. I think this has been a mistake in the first place. It makes it more difficult to use I'm currently working |
Yes, I think so. However, I don't think we can get rid of Anyway I don't think that is directly relevant to this |
Fix exit status / wait status on non-Unix cfg(unix) platforms Fixes rust-lang#114593 Needs FCP due to behavioural changes (NB only on non-Unix `#[cfg(unix)]` platforms). Also, I think this is likely to break in CI. I have not been yet able to compile the new bits of `process_unsupported.rs`, although I have compiled the new module. I'd like some help from people familiar with eg emscripten and fuchsia (which are going to be affected, I think).
(Terminology: in this ticket "
ExitCode
" and "exit status" mean a value like one passed toexit
. "ExitStatus
" and "wait status" mean a value like one returned as the status value fromwait
.)Rust supports a number of platforms which are not Unix but which are
#[cfg(unix)]
and providestd::process
vialibrary/std/src/sys/unix/process/process_unsupported.rs
In rust-lang/libs-team#158 and #106425 (comment) we seem to have decided that we would like to
impl From<ExitCode> for ExitStatus
. This makes semantic sense. A wait status ought to be able to represent any kind of process completion including an exit status.Most of
process_unsupported
is an implementation ofimp::ExitStatus
(which is used to provide actual publicprocess::ExitStatus
). But it has some strange properties which are both unreasonable, and blocking for thatFrom
impl.Properties that
ExitStatus
actually has right now on these non-unixunix
platformsExitStatusExt::from_raw
andinto_raw
appear to allow conversion back and forth to and fromc_int
. (This is implied by providingExitStatusExt
.)But
ExitStatus::into_raw
always returns0
- even forfrom_raw(nonzero)
. So the raw conversions are unfaithful.ExitStatus::code
always returnsNone
, even forfrom_raw(0)
.In Nightly, you can call
ExitStatus::exit_ok
and get anExitStatusError
. ThenExitStatusError::code
will give youOption<ExitCode>
. This will always returnNone
regardless of the input values.Properties that
ExitStatus
ought to haveGiven that
ExitStatus
(the wait status) is inhabited everywhere, even when you can't actually launch and reap a process, and so isExitCode
(the exit status), you should be able to make anExitStatus
(wait status) representing a hypothetical process exit, at the very least.Certainly
unix::ExitStatusExt::from_raw(0).is_success()
ought to betrue
; there are no unix-like platforms where a zero wait status means anything other than successful termination, and on Unix successful process termination is represented as a zero exit status. So we need to be able to represent an 8-bit exit status.ExitStatus::code()
should be capable of returningSome
.ExitStatus::from_raw(v).into_raw()
should always returnv
.Proposal
Given that we have raw conversions we must define what those integers mean.
These non-Unix platforms are providing this API, with stubbed-out implementations, to make it easier to port software. That suggests that we should provide an emulation. Therefore:
process_unsupported::ExitStatus
ought to contain a value in "traditional unixexit statuswait status" format. This format isn't formally standardised, but roughly speaking it'sexit_status << 8
, orsignal | (core_dumped ? 128 : 0)
. The methods onExitStatus
inprocess_unspported.rs
ought to decode that trad format and return non-"null" values as appropriate.Stability
This would be a behavioural change for all the (stable) accessors in
ExitStatusExt
, but only on platforms usingprocess_unsupported.rs
. None of those platforms are actually unix, by definition. They're just pretending (in some cases, for good reasons).The behavioural change is only visible if
ExitStatus::from_raw
orExitStatus as Default
is used.ExitStatus as Default
is not in tree yet, but it is beingmerged in #106425 (FCP completed there). The documentation I write in the followup #114588 is lies on these broken platforms:ExitStatus::default().success()
returnsfalse
there. I think this is a bug.from_raw
is longstanding. One might argue that none of these changes can be observed by a non-buggy program, sincefrom_raw
says "from the raw underlying integer status value fromwait
" and on these platforms there can be no such values since there is nowait
. This is surely too much sophistry. However, in practice, it seems unlikely that many programs would be broken in practice by changingExitStatus::from_raw(0).code()
to returnSome(SUCCESS)
,.success()
to returntrue
, etc.;and it seems unlikely that there are many programs at all using
ExitStatus::from_raw(v)
wherev != 0
.It would make sense to make all these behavioural changes all at once, so provide nontrivial implementations of
signal
,core_dumped
,stopped_signal
andcontinued
, as well ascode
.Alternatives
Declare that the raw value is precisely the exit status, not shifted left. Or declare that it's the exit status shifted, but don't support the other kinds of value.
The text was updated successfully, but these errors were encountered: