Handle clap errors manually and don't reset SIGPIPE (#6012)

Instead of resetting `SIGPIPE` to the system default handler, we now
handle a clap error manually and ignore any error when writing to
`stdout`/`stderr`. In this way, the node does not silently stops when it
encounters a `SIGPIPE` in normal mode and we still support piping of the
cli output.
This commit is contained in:
Bastian Köcher
2020-05-13 19:43:38 +02:00
committed by GitHub
parent b99033368b
commit daf8cf0600
2 changed files with 21 additions and 21 deletions
+21 -19
View File
@@ -129,7 +129,27 @@ pub trait SubstrateCli: Sized {
AppSettings::SubcommandsNegateReqs,
]);
<Self as StructOpt>::from_clap(&app.get_matches_from(iter))
let matches = match app.get_matches_from_safe(iter) {
Ok(matches) => matches,
Err(mut e) => {
// To support pipes, we can not use `writeln!` as any error
// results in a "broken pipe" error.
//
// Instead we write directly to `stdout` and ignore any error
// as we exit afterwards anyway.
e.message.extend("\n".chars());
if e.use_stderr() {
let _ = std::io::stderr().write_all(e.message.as_bytes());
std::process::exit(1);
} else {
let _ = std::io::stdout().write_all(e.message.as_bytes());
std::process::exit(0);
}
},
};
<Self as StructOpt>::from_clap(&matches)
}
/// Helper function used to parse the command line arguments. This is the equivalent of
@@ -264,21 +284,3 @@ fn kill_color(s: &str) -> String {
}
RE.replace_all(s, "").to_string()
}
/// Reset the signal pipe (`SIGPIPE`) handler to the default one provided by the system.
/// This will end the program on `SIGPIPE` instead of panicking.
///
/// This should be called before calling any cli method or printing any output.
pub fn reset_signal_pipe_handler() -> Result<()> {
#[cfg(target_family = "unix")]
{
use nix::sys::signal;
unsafe {
signal::signal(signal::Signal::SIGPIPE, signal::SigHandler::SigDfl)
.map_err(|e| Error::Other(e.to_string()))?;
}
}
Ok(())
}