-
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
Tracking issue for std::process::ExitCode (feature process_exitcode_placeholder) #48711
Comments
From discussions we've had in the WG-CLI gitter, something that would be amazing to have would be a way to enumerate all possible exit codes for a program. We're currently looking into automatically creating man pages for CLIs, and being able to automatically document which exit codes are possible would let Rust do something that no other language does. I don't have any proposals on how to best approach this, but figured it would probably be worth bringing up. Thanks! edit: PS. I hope this is the right thread to mention this in! Apologies if I got it wrong! |
@yoshuawuyts Sounds like a cool feature! I don't know if this struct is exactly the thing you'd need, though, since it'll probably just remain a newtype. Maybe you could have a custom derive to generate |
Would you consider also adding the definitions from For example:-
See https://github.com/bminor/musl/blob/master/include/sysexits.h for a full list. All part of any POSIX libc. In particular, it'd be nice if an uncaught panic resulted in an exit code of |
@raphaelcohn The design space here is still wide open, so it's certainly possible. There are some thoughts in the IRLO thread, but really it needs someone to dig in and make a proposal. As for uncaught panics, I believe they currently give a 101 exit code, not EXIT_FAILURE. |
@yoshuawuyts Has any progress been made on this? I'm wondering if https://github.com/JoshMcguigan/exit could be expanded or somehow tied into some broader cli library to solve this problem? |
@JoshMcguigan hey, thanks for asking! I read your blog post, and I really like the work you've been doing! To answer your question: man now supports defining custom exit codes. However we haven't created any sort of bridge (e.g. the closest we've come is to create a bridge to clap). That said, I do have some thoughts on this. I was chatting with @davidbarsky last week about the It's worth mentioning that at the Rust all-hands there was talk about moving error chains ( I'm wondering if we could somehow merge all of these features into a single crate, and find a solution that works for most people. The features I'm currently thinking of are:
Haha, I hope all this makes sense. Sorry it's a lot of text; it's something I've been thinking about for a few months, but didn't quite get a chance to connect all pieces until now. I hope this is useful! |
I'm not sure if this or the I'm curious what needs doing before I can return an arbitrary exit code (between 1-127) from main using I've read most of the links in #43301 and the preRFC but am still uncertain about status of my need, or how go about implementing it. |
Add From<u8> for ExitCode This should cover a mostly cross-platform subset of supported exit codes. We decided to stick with `u8` initially since its the common subset between all platforms that we support (excluding wasm which I think only works with `true` or `false`). Posix is supposed to take i32s, but in practice many unix platforms mask out all but the low 8 bits or in some cases the 8-15th bits. Windows takes a u32 instead of an i32. Bourne-compatible shells also report signals as exitcode 128 + `signal_no`, so there's some ambiguity there when returning exit codes > 127, but it is possible to disambiguate them on the other side so we decided against restricting the possible codes further than to `u8`. ## Related - Detailed analysis of exit code support on various platforms: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426 - rust-lang#48711 - rust-lang#43301 - https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Termination.2FExit.20Status.20Stabilization
Add From<u8> for ExitCode This should cover a mostly cross-platform subset of supported exit codes. We decided to stick with `u8` initially since its the common subset between all platforms that we support (excluding wasm which I think only works with `true` or `false`). Posix is supposed to take i32s, but in practice many unix platforms mask out all but the low 8 bits or in some cases the 8-15th bits. Windows takes a u32 instead of an i32. Bourne-compatible shells also report signals as exitcode 128 + `signal_no`, so there's some ambiguity there when returning exit codes > 127, but it is possible to disambiguate them on the other side so we decided against restricting the possible codes further than to `u8`. ## Related - Detailed analysis of exit code support on various platforms: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426 - rust-lang#48711 - rust-lang#43301 - https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Termination.2FExit.20Status.20Stabilization
Add From<u8> for ExitCode This should cover a mostly cross-platform subset of supported exit codes. We decided to stick with `u8` initially since its the common subset between all platforms that we support (excluding wasm which I think only works with `true` or `false`). Posix is supposed to take i32s, but in practice many unix platforms mask out all but the low 8 bits or in some cases the 8-15th bits. Windows takes a u32 instead of an i32. Bourne-compatible shells also report signals as exitcode 128 + `signal_no`, so there's some ambiguity there when returning exit codes > 127, but it is possible to disambiguate them on the other side so we decided against restricting the possible codes further than to `u8`. ## Related - Detailed analysis of exit code support on various platforms: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426 - rust-lang#48711 - rust-lang#43301 - https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Termination.2FExit.20Status.20Stabilization
Add From<u8> for ExitCode This should cover a mostly cross-platform subset of supported exit codes. We decided to stick with `u8` initially since its the common subset between all platforms that we support (excluding wasm which I think only works with `true` or `false`). Posix is supposed to take i32s, but in practice many unix platforms mask out all but the low 8 bits or in some cases the 8-15th bits. Windows takes a u32 instead of an i32. Bourne-compatible shells also report signals as exitcode 128 + `signal_no`, so there's some ambiguity there when returning exit codes > 127, but it is possible to disambiguate them on the other side so we decided against restricting the possible codes further than to `u8`. ## Related - Detailed analysis of exit code support on various platforms: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426 - rust-lang#48711 - rust-lang#43301 - https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Termination.2FExit.20Status.20Stabilization
Stabilized in #93840. |
Hi all, been looking through a few issues but didn't see what I was looking for. Is there any intent for the following behavior: use std::process::{ExitCode, Termination};
#[derive(Debug)]
pub enum MyError {
Internal,
Other,
}
impl Termination for MyError {
fn report(self) -> ExitCode {
match self {
MyError::Internal => ExitCode::from(1),
MyError::Other => ExitCode::from(255),
}
}
}
fn main() -> Result<(), MyError> {
Err(MyError::Other)?;
Ok(())
} Where the program would return the error code of the Error from the Result type? |
@gluax the current plan is to expose this functionality through the generic member access RFC / provider API once those have been added to fn provide_context<'a>(&'a self, mut request: &mut Request<'a>) {
request
.provide_ref::<Backtrace>(&self.backtrace)
.provide_value::<ExitCode>(self.exit_code);
} Note: the RFC is a bit out of date and needs to be updated still |
Agreed, I think it's better for Could we not do something like the following: impl<T, E> Termination for Result<T, E> where
E: Termination {
// Do match pattern here and grab report but also display the error as is standard.
}
impl<T, E> Termination for Result<T, E> where
E: !Termination {
// This would be the old impl making it valid for all E types who do not have Termination implemented.
} I'm not entirely sure the above pattern would work, but I feel something akin to it should be possible? |
To my knowledge, this kind of feature cannot be implemented. Unfortunately, we must also deal with the fact that stable Your example makes use of negative trait bounds, which is a feature we are highly unlikely to accept because, as far as I know, it makes trait solving infeasible1. I know @nikomatsakis suggested a variant of negative bounds in which a negative bound implies that you have an explicit negative impl, but then you'd still need to cover the case where you have neither a positive impl nor a negative impl, and I'm not sure how that would work. I think it's more likely that we'll want to solve this problem through specialization, but specialization like this— Footnotes |
@yaahc thanks for that clarification and explanation! |
Actually, your initial snippet is just going to work in a few releases, those two Edit: oh, actually it's not going to use the |
@jplatte is there? I see the trait implemented as |
Yeah, I shouldn't comment in the middle of the night with half my brain still asleep 😅 yaahc was entirely right that using a |
I came here looking for the Termination impl on the E side of Result after migrating to error_stack and I'm so confused. Why was #97803 (comment) accepted as a common use case for implementing termination on the success side? The code didn't improve IMO.
If what @yaahc said is true then this is so sad. Everyone is now doomed to write: match result {
Ok(o) => o.report(),
Err(err) => {
drop(writeln!(io::stderr(), "Error: {err:?}"));
err.report()
}
} When you could have just written Is it possible to reverse this decision in the next edition? And unless I completely misunderstood the use case, could the people involved evaluate the process that led to this state? Reading the PR comments it seems like this was a quick and dirty decision that didn't have time to receive input from stakeholders. At the very least a separate issue should have been created in the https://github.com/rust-lang/libs-team repo. |
If this is not possible, I just thought of something that would make the situation a little less bad. Since we'd be stuck with the convention of having Termination on the success side, we could do the same for Option and |
This tracking issue no longer seems to be tracking anything. The relevant feature has been shipped some time ago. There's additional work we may want to do in the future, but that's not being tracked by this issue. |
https://doc.rust-lang.org/nightly/std/process/struct.ExitCode.html
Code added in #48497 (comment); changed to this issue in #48618
Creating this because
?
-in-main
(#43301) will probably stabilize firstThis is very minimal so far, and hasn't had an RFC. IRLO thread for what it should be.
Unresolved Questions
PartialEq
or addis_success()
/is_failure()
methods to ExitCode? Brought up in Change Termination::report return type to ExitCode #93442 (comment) and in the resolved comment thread initiated by @scottmcm in that same threadThe text was updated successfully, but these errors were encountered: