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
commit75ecf543eb4077f6918fbb020c39315311a9decf (patch)
tree89e4dffe0d9acff85d7d9ad69ebd3db98a9ba97e
parent15e0ad34f8a86b685dc6fddae2813560930ca1a7 (diff)
downloadnitrocli-75ecf543eb4077f6918fbb020c39315311a9decf.tar.gz
nitrocli-75ecf543eb4077f6918fbb020c39315311a9decf.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);
}