diff options
author | Daniel Mueller <deso@posteo.net> | 2019-01-12 11:41:52 -0800 |
---|---|---|
committer | Daniel Mueller <deso@posteo.net> | 2019-01-12 11:41:52 -0800 |
commit | 2095641dd9d1245d7f7425e008f4bff8bfcd8a84 (patch) | |
tree | 11f8da19cf7d1f771ec822731d795cb1009476e3 | |
parent | 44b8c57a6f8701c50b179e482deca79a9e4e7acb (diff) | |
download | nitrocli-2095641dd9d1245d7f7425e008f4bff8bfcd8a84.tar.gz nitrocli-2095641dd9d1245d7f7425e008f4bff8bfcd8a84.tar.bz2 |
Properly flush stdout before process exit
We exit the program using the process::exit function. This function just
exits the program directly, without any cleanup. That can be a problem
because IO buffers may not be flushed either. For a (typically) line
buffered entity like stdout that may result in data not terminated by a
newline symbol being not displayed properly.
This change explicitly flushes stdout before exiting the process to
alleviate this problem. Note that stderr output is unaffected, because
stderr is not buffered by design.
-rw-r--r-- | nitrocli/src/main.rs | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs index 8d5953b..ff6db0f 100644 --- a/nitrocli/src/main.rs +++ b/nitrocli/src/main.rs @@ -142,15 +142,29 @@ fn run<'ctx, 'io: 'ctx>(ctx: &'ctx mut RunCtx<'io>, args: Vec<String>) -> i32 { } fn main() { + use std::io::Write; + + let mut stdout = io::stdout(); + let mut stderr = io::stderr(); let args = env::args().collect::<Vec<_>>(); let ctx = &mut RunCtx { - stdout: &mut io::stdout(), - stderr: &mut io::stderr(), + stdout: &mut stdout, + stderr: &mut stderr, admin_pin: env::var_os(NITROCLI_ADMIN_PIN), user_pin: env::var_os(NITROCLI_USER_PIN), new_admin_pin: env::var_os(NITROCLI_NEW_ADMIN_PIN), new_user_pin: env::var_os(NITROCLI_NEW_USER_PIN), }; - process::exit(run(ctx, args)); + let rc = run(ctx, args); + // We exit the process the hard way below. The problem is that because + // of this, buffered IO may not be flushed. So make sure to explicitly + // flush before exiting. Note that stderr is unbuffered, alleviating + // the need for any flushing there. + // Ideally we would just make `main` return an i32 and let Rust deal + // with all of this, but the `process::Termination` functionality is + // still unstable and we have no way to convince the caller to "just + // exit" without printing additional information. + let _ = stdout.flush(); + process::exit(rc); } |