summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mueller <deso@posteo.net>2019-01-12 11:41:52 -0800
committerDaniel Mueller <deso@posteo.net>2019-01-12 11:41:52 -0800
commit2095641dd9d1245d7f7425e008f4bff8bfcd8a84 (patch)
tree11f8da19cf7d1f771ec822731d795cb1009476e3
parent44b8c57a6f8701c50b179e482deca79a9e4e7acb (diff)
downloadnitrocli-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.rs20
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);
}