From 858f9f886efdddf619c90bf5448395d6a2535fb0 Mon Sep 17 00:00:00 2001 From: clabby Date: Tue, 17 Sep 2024 13:57:47 -0400 Subject: [PATCH] feat(host): Exit with client status in native mode (#530) * feat(host): Exit with client status in native mode * panic on error, `Err(_)` in main returns `1` status. * lint --- bin/client/src/kona.rs | 17 +++++++++++-- bin/host/src/lib.rs | 55 ++++++++++++++++++++++++------------------ bin/host/src/main.rs | 13 ++++++++-- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/bin/client/src/kona.rs b/bin/client/src/kona.rs index f2f5fc60..8f9804a0 100644 --- a/bin/client/src/kona.rs +++ b/bin/client/src/kona.rs @@ -74,8 +74,21 @@ fn main() -> Result<()> { // EPILOGUE // //////////////////////////////////////////////////////////////// - assert_eq!(number, boot.l2_claim_block); - assert_eq!(output_root, boot.l2_claim); + if number != boot.l2_claim_block || output_root != boot.l2_claim { + tracing::error!( + target: "client", + "Failed to validate L2 block #{number} with output root {output_root}", + number = number, + output_root = output_root + ); + kona_common::io::print(&alloc::format!( + "Failed to validate L2 block #{} with output root {}\n", + number, + output_root + )); + + kona_common::io::exit(1); + } tracing::info!( target: "client", diff --git a/bin/host/src/lib.rs b/bin/host/src/lib.rs index 90181b63..4789e9a3 100644 --- a/bin/host/src/lib.rs +++ b/bin/host/src/lib.rs @@ -15,7 +15,7 @@ pub use cli::{init_tracing_subscriber, HostCli}; use fetcher::Fetcher; use server::PreimageServer; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, bail, Result}; use command_fds::{CommandFdExt, FdMapping}; use futures::FutureExt; use kona_common::FileDescriptor; @@ -29,7 +29,7 @@ use std::{ sync::Arc, }; use tokio::{process::Command, sync::RwLock, task}; -use tracing::{error, info}; +use tracing::{debug, error, info}; use util::Pipe; /// Starts the [PreimageServer] in the primary thread. In this mode, the host program has been @@ -77,7 +77,15 @@ pub async fn start_server(cfg: HostCli) -> Result<()> { /// Starts the [PreimageServer] and the client program in separate threads. The client program is /// ran natively in this mode. -pub async fn start_server_and_native_client(cfg: HostCli) -> Result<()> { +/// +/// ## Takes +/// - `cfg`: The host configuration. +/// +/// ## Returns +/// - `Ok(exit_code)` if the client program exits successfully. +/// - `Err(_)` if the client program failed to execute, was killed by a signal, or the host program +/// exited first. +pub async fn start_server_and_native_client(cfg: HostCli) -> Result { let hint_pipe = util::bidirectional_pipe()?; let preimage_pipe = util::bidirectional_pipe()?; @@ -121,13 +129,21 @@ pub async fn start_server_and_native_client(cfg: HostCli) -> Result<()> { // Execute both tasks and wait for them to complete. info!("Starting preimage server and client program."); + let exit_status; tokio::select!( - r = util::flatten_join_result(server_task) => r?, - r = util::flatten_join_result(program_task) => r? + r = util::flatten_join_result(server_task) => { + r?; + error!(target: "kona_host", "Preimage server exited before client program."); + bail!("Host program exited before client program."); + }, + r = util::flatten_join_result(program_task) => { + exit_status = r?; + debug!(target: "kona_host", "Client program has exited with status {exit_status}."); + } ); - info!(target: "kona_host", "Preimage server and client program have exited."); + info!(target: "kona_host", "Preimage server and client program have joined."); - Ok(()) + Ok(exit_status) } /// Starts the preimage server in a separate thread. The client program is ran natively in this @@ -176,13 +192,13 @@ where /// - `rx`: The receiver to wait for the preimage server to exit. /// /// ## Returns -/// - `Ok(())` if the client program exits successfully. -/// - `Err(_)` if the client program exits with a non-zero status. +/// - `Ok(exit_code)` if the client program exits successfully. +/// - `Err(_)` if the client program failed to execute or was killed by a signal. pub async fn start_native_client_program( cfg: HostCli, hint_pipe: Pipe, preimage_pipe: Pipe, -) -> Result<()> { +) -> Result { // Map the file descriptors to the standard streams and the preimage oracle and hint // reader's special file descriptors. let mut command = @@ -220,19 +236,10 @@ pub async fn start_native_client_program( ]) .expect("No errors may occur when mapping file descriptors."); - let status = command - .status() - .await - .map_err(|e| { - error!(target: "client_program", "Failed to execute client program: {:?}", e); - anyhow!("Failed to execute client program: {:?}", e) - })? - .success(); + let status = command.status().await.map_err(|e| { + error!(target: "client_program", "Failed to execute client program: {:?}", e); + anyhow!("Failed to execute client program: {:?}", e) + })?; - if !status { - error!(target: "client_program", "Client program exited with a non-zero status."); - return Err(anyhow!("Client program exited with a non-zero status.")); - } - - Ok(()) + status.code().ok_or_else(|| anyhow!("Client program was killed by a signal.")) } diff --git a/bin/host/src/main.rs b/bin/host/src/main.rs index f3f3f8a8..648531f6 100644 --- a/bin/host/src/main.rs +++ b/bin/host/src/main.rs @@ -1,7 +1,7 @@ use anyhow::Result; use clap::Parser; use kona_host::{init_tracing_subscriber, start_server, start_server_and_native_client, HostCli}; -use tracing::info; +use tracing::{error, info}; #[tokio::main(flavor = "multi_thread")] async fn main() -> Result<()> { @@ -11,7 +11,16 @@ async fn main() -> Result<()> { if cfg.server { start_server(cfg).await?; } else { - start_server_and_native_client(cfg).await?; + let status = match start_server_and_native_client(cfg).await { + Ok(status) => status, + Err(e) => { + error!(target: "kona_host", "Exited with an error: {:?}", e); + panic!("{e}"); + } + }; + + // Bubble up the exit status of the client program. + std::process::exit(status as i32); } info!("Exiting host program.");