Skip to content
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

Support checking whether std::process::ExitCode represents success or failure #113081

Open
nya3jp opened this issue Jun 27, 2023 · 4 comments
Open
Labels
A-process Area: `std::process` and `std::env` T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@nya3jp
Copy link

nya3jp commented Jun 27, 2023

IIUC there is no good way to check whether a std::process::ExitCode corresponds to success or failure. This is cumbersome, for example, when we want to check the exit code just before actually exiting.

use std::process::ExitCode;

fn real_main() -> ExitCode {
    // ... do something ...
    ExitCode::FAILED
}

fn main() -> ExitCode {
    let exit_code = real_main();
    
    // For now, the only way to check if `exit_code` is success is to check its
    // Debug serialization:
    if format!("{:?}", exit_code) != "ExitCode(unix_exit_status(0))" {
        eprintln!("FAILED");
    }
    
    // Ideally we want to write this like:
    /*
    if !exit_code.is_success() {
        eprintln!("FAILED!");
    }
    */

    exit_code
}

Can we add methods to std::process::ExitCode checking whether it is success or failure?

It seems like is_success/is_failure were considered when stabilizing std::process::ExitCode, but it was left as an unresolved question. #48711

@jyn514
Copy link
Member

jyn514 commented Jun 27, 2023

the docs for exit code say this:

ExitCode is intended to be consumed only by the standard library (via Termination::report()), and intentionally does not provide accessors like PartialEq, Eq, or Hash

why do you want to introspect an exit code (instead of e.g. returning Result or an integer status from real_main)?

@jyn514 jyn514 added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. A-process Area: `std::process` and `std::env` labels Jun 27, 2023
@nmwael
Copy link

nmwael commented Nov 16, 2023

as I see it, it would be very nice to be able to check this in tests..

@nya3jp
Copy link
Author

nya3jp commented Nov 19, 2023

Sorry for no update for long time...

@jyn514 is right, we can resolve the case in my first post by introducing a custom type wrapping integer. However I'm not sure if it's desirable.

I also realized that it's more problematic when we want to unit-test functions that returns ExitCode. Since the only way to "use" ExitCode is to return it from the main function, it's difficult to test such functions. Note that this property is unique to ExitCode; for example, std::fs::OpenOptions can't be inspected too, but it can be still testable by using it by calling open can checking its behavior. But such behavior testing is difficult for ExitCode.

Of course we can make those functions testable by replacing all usage of ExitCode with a custom type, but it sounds inconvenient if all serious programs with unit test coverage must define its own ExitCode-like type.

@bradzacher
Copy link

For my usecase I am building a CLI where each command returns an ExitCode, eg

fn main() -> ExitCode {
  let command = parse_cli_args();
  switch command {
    CommandFoo => command_foo(),
    CommandBar => command_bar(),
    // ...
  }
}

I was looking into how I might provide "meta commands" - commands that batch some commands together for DevX improvements. But I ofc don't want to run the next command if the previous command failed, eg

fn command_combined() => ExitCode {
  let result = command_foo();
  if result != ExitCode::SUCCESS {
    return result;
  }

  command_bar()
}

But currently it looks like this is not possible - and instead I'll need to implement my own enum.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-process Area: `std::process` and `std::env` T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants