From fbf6099e13cdb6f02426aad989ff9c28301735f1 Mon Sep 17 00:00:00 2001 From: Hansie Odendaal Date: Thu, 21 Nov 2024 14:51:16 +0200 Subject: [PATCH] Fix base node shutdown Fixed the base node shutdown on Ubuntu whereas pressing Ctrl-C multiple times rendered the command line interface in an undefined state. This was not issue on Windows. Note: The change to 'base_layer\core\src\base_node\tari_pulse_service\mod.rs' is just to enable testing (get rid of the repeated command-line spam), and will be fixed in #6696. --- .../minotari_node/src/commands/cli_loop.rs | 29 ++++++++++++++++--- .../minotari_node/src/commands/command/mod.rs | 6 ++++ applications/minotari_node/src/config.rs | 3 +- .../src/base_node/tari_pulse_service/mod.rs | 2 +- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/applications/minotari_node/src/commands/cli_loop.rs b/applications/minotari_node/src/commands/cli_loop.rs index a3cd47b7f5..be4a34c7e2 100644 --- a/applications/minotari_node/src/commands/cli_loop.rs +++ b/applications/minotari_node/src/commands/cli_loop.rs @@ -16,7 +16,7 @@ use tokio::{signal, time}; use crate::{ commands::{ cli, - command::{CommandContext, WatchCommand}, + command::{Args, CommandContext, WatchCommand}, parser::Parser, reader::CommandReader, }, @@ -87,7 +87,9 @@ impl CliLoop { } else { while !self.done { self.watch_loop().await; - self.execute_command().await; + if !self.done { + self.execute_command().await; + } } } } @@ -129,12 +131,19 @@ impl CliLoop { println!("Wrong command to watch `{}`. Failed with: {}", line, err); } else { let mut events = EventStream::new(); - loop { + while !self.done { let interval = time::sleep(interval); tokio::select! { _ = interval => { if let Err(err) = self.context.handle_command_str(line).await { println!("Watched command `{}` failed: {}", line, err); + } else { + let args: Result = line.parse(); + if let Ok(command) = args { + if command.is_quit() { + self.done = true; + } + } } continue; }, @@ -158,7 +167,9 @@ impl CliLoop { } } } - crossterm::execute!(io::stdout(), cursor::MoveToNextLine(1)).ok(); + if !self.done { + crossterm::execute!(io::stdout(), cursor::MoveToNextLine(1)).ok(); + } } terminal::disable_raw_mode().ok(); } @@ -183,6 +194,13 @@ impl CliLoop { _ = interval => { if let Err(err) = self.context.handle_command_str(line).await { println!("Watched command `{}` failed: {}", line, err); + } else { + let args: Result = line.parse(); + if let Ok(command) = args { + if command.is_quit() { + self.done = true; + } + } } continue; }, @@ -242,6 +260,9 @@ impl CliLoop { } else { self.done = true; } + if self.done && !self.shutdown_signal.is_triggered() { + self.context.shutdown.trigger(); + } }, _ = self.shutdown_signal.wait() => { self.done = true; diff --git a/applications/minotari_node/src/commands/command/mod.rs b/applications/minotari_node/src/commands/command/mod.rs index 14184a036b..fa11545b02 100644 --- a/applications/minotari_node/src/commands/command/mod.rs +++ b/applications/minotari_node/src/commands/command/mod.rs @@ -97,6 +97,12 @@ pub struct Args { pub command: Command, } +impl Args { + pub fn is_quit(&self) -> bool { + matches!(self.command, Command::Quit(_) | Command::Exit(_)) + } +} + #[derive(Debug, Subcommand, EnumVariantNames)] #[strum(serialize_all = "kebab-case")] pub enum Command { diff --git a/applications/minotari_node/src/config.rs b/applications/minotari_node/src/config.rs index f6b704801b..f209e5b23a 100644 --- a/applications/minotari_node/src/config.rs +++ b/applications/minotari_node/src/config.rs @@ -142,7 +142,8 @@ pub struct BaseNodeConfig { pub state_machine: BaseNodeStateMachineConfig, /// Obscure GRPC error responses pub report_grpc_error: bool, - // Interval to check if the base node is still in sync with the network + /// Interval to check if the base node is still in sync with the network + #[serde(with = "serializers::seconds")] pub tari_pulse_interval: Duration, } diff --git a/base_layer/core/src/base_node/tari_pulse_service/mod.rs b/base_layer/core/src/base_node/tari_pulse_service/mod.rs index 20de1f4339..5d2a277533 100644 --- a/base_layer/core/src/base_node/tari_pulse_service/mod.rs +++ b/base_layer/core/src/base_node/tari_pulse_service/mod.rs @@ -118,6 +118,7 @@ impl TariPulseService { let mut interval = time::interval(self.config.check_interval); let mut interval_failed = time::interval(Duration::from_millis(100)); loop { + interval.tick().await; let passed_checkpoints = match self.passed_checkpoints(&mut base_node_service).await { Ok(passed) => passed, Err(err) => { @@ -130,7 +131,6 @@ impl TariPulseService { notify_passed_checkpoints .send(!passed_checkpoints) .expect("Channel should be open"); - interval.tick().await; } }