Skip to content

std::process::Command output() method error handling hazards #73126

Closed as not planned
@ijackson

Description

Hi. Normally, Rust makes it difficult to accidentally write buggy code. This is one of its great strengths. However, the API of output() on std::process::Command API has two serious error handling hazards:

  1. It requires the user to explicitly fish out the program's exit status and check it.
  2. It requires the user to explicitly deal, somehow, with the program's stderr output (if any).

See the example below.

I think this is very difficult to fix with the current return value from output(). It seems to me that there should be a new function whose behaviour is as follows:

  • Unless the user explictly called .stderr(...) when building the Command, any nonempty stderr is treated as an error, giving an Err return value (whose Debug impl prints the stderr output).
  • Nonzero exit status is treated as an error, giving an Err return value,
  • In case of nonzero exit status together with nonempty stderr output (the usual case) the error object contains both (and its Debug impl displays both).
  • The returned value is purely the actual stdout.

I don't know what this should be called. Unfortunately the name output has been taken for the more hazardous, raw, function. Which we must retain because if you want to run a command that sometimes succeeds returning nonzero (eg, diff) you need something like it.

(See also #70186 which is about the return value from spawn(). I am about to file another issue about the return value from wait())

use std::process::*;
use std::io::stdout;
use std::io::Write;

fn main() {
    let command = ["ls","--no-such-option"];
    
    let output = Command::new(command[0])
                     .args(&command[1..])
                     .output()
                     .expect("output() failed");
    println!("Output from {:?}:", &command);
    stdout().write_all(output.stdout.as_slice()).expect("write failed");
    
    println!("All went well!")
}

(Playground)

Actual output:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.72s
     Running `target/debug/playground`

Standard Output

Output from ["ls", "--no-such-option"]:
All went well!

Expected output:

Some kind of compiler warning. Or something in the docs to say not to use .output() (and, therefore, something convenient to use instead).

Metadata

Assignees

No one assigned

    Labels

    A-processArea: `std::process` and `std::env`C-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions