Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix test failures by flushing output streams before exiting Zebra #2911

Merged
merged 1 commit into from
Oct 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions zebra-state/src/service/finalized_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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();
}
}

Expand Down Expand Up @@ -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.
Comment on lines +497 to +498
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😭💀

//
// 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
Expand Down
24 changes: 16 additions & 8 deletions zebrad/src/application.rs
Original file line number Diff line number Diff line change
@@ -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();

Expand Down Expand Up @@ -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();
Comment on lines +419 to +420
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


if let Err(e) = self.state().components.shutdown(self, shutdown) {
fatal_error(self, &e)
}
Expand Down