Try flushing streams before exiting Zebra (#2911)

This commit is contained in:
teor 2021-10-20 23:57:09 +10:00 committed by GitHub
parent 92634f788b
commit e277975d85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 14 deletions

View File

@ -5,7 +5,14 @@ mod disk_format;
#[cfg(test)]
mod tests;
use std::{borrow::Borrow, collections::HashMap, convert::TryInto, path::Path, sync::Arc};
use std::{
borrow::Borrow,
collections::HashMap,
convert::TryInto,
io::{stderr, stdout, Write},
path::Path,
sync::Arc,
};
use zebra_chain::{
amount::NonNegative,
@ -126,8 +133,8 @@ impl FinalizedState {
// So we want to drop it before we exit.
tracing::info!("closing cached state");
std::mem::drop(new_state);
tracing::info!("exiting Zebra");
std::process::exit(0);
Self::exit_process();
}
}
@ -467,20 +474,36 @@ impl FinalizedState {
// We'd like to drop the database here, because that closes the
// column families and the database. But Rust's ownership rules
// make that difficult, so we just flush instead.
// make that difficult, so we just flush and delete ephemeral data instead.
// TODO: remove these extra logs once bugs like #2905 are fixed
self.db.flush().expect("flush is successful");
tracing::info!("flushed database to disk");
self.delete_ephemeral();
tracing::info!("exiting Zebra");
std::process::exit(0);
Self::exit_process();
}
result.map_err(Into::into)
}
/// Exit the host process.
///
/// Designed for debugging and tests.
fn exit_process() -> ! {
tracing::info!("exiting Zebra");
// Some OSes require a flush to send all output to the terminal.
// Zebra's logging doesn't depend on `tokio`, so we flush the stdlib sync streams.
//
// TODO: if this doesn't work, send an empty line as well.
let _ = stdout().lock().flush();
let _ = stderr().lock().flush();
std::process::exit(0);
}
/// Commit a finalized block to the state.
///
/// It's the caller's responsibility to ensure that blocks are committed in

View File

@ -1,20 +1,19 @@
//! Zebrad Abscissa Application
use crate::{commands::ZebradCmd, components::tracing::Tracing, config::ZebradConfig};
use std::{io::Write, process};
use abscissa_core::{
application::{self, AppCell},
config,
config::Configurable,
terminal::component::Terminal,
terminal::ColorChoice,
application::{self, fatal_error, AppCell},
config::{self, Configurable},
terminal::{component::Terminal, stderr, stdout, ColorChoice},
Application, Component, EntryPoint, FrameworkError, Shutdown, StandardPaths, Version,
};
use application::fatal_error;
use std::process;
use zebra_network::constants::PORT_IN_USE_ERROR;
use zebra_state::constants::{DATABASE_FORMAT_VERSION, LOCK_FILE_ERROR};
use crate::{commands::ZebradCmd, components::tracing::Tracing, config::ZebradConfig};
/// Application state
pub static APPLICATION: AppCell<ZebradApp> = AppCell::new();
@ -411,6 +410,15 @@ impl Application for ZebradApp {
}
fn shutdown(&mut self, shutdown: Shutdown) -> ! {
// Some OSes require a flush to send all output to the terminal.
// zebrad's logging uses Abscissa, so we flush its streams.
//
// TODO:
// - if this doesn't work, send an empty line as well
// - move this code to the tracing component's `before_shutdown()`
let _ = stdout().lock().flush();
let _ = stderr().lock().flush();
if let Err(e) = self.state().components.shutdown(self, shutdown) {
fatal_error(self, &e)
}