From ed36cead11230563420c4e2cf3aec4280b2198c7 Mon Sep 17 00:00:00 2001 From: kxxt Date: Tue, 6 Aug 2024 10:18:31 +0800 Subject: [PATCH] fix: don't hang if tracer crashed --- src/event.rs | 1 + src/main.rs | 36 +++++++++++++++++++++++------- src/tracer.rs | 9 ++++++-- src/tui.rs | 59 +++++++++++++++++++++++++++++--------------------- src/tui/app.rs | 11 ++++++++++ 5 files changed, 81 insertions(+), 35 deletions(-) diff --git a/src/event.rs b/src/event.rs index 940f8347..2bfaf99f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -51,6 +51,7 @@ pub enum Event { pub enum TracerMessage { Event(TracerEvent), StateUpdate(ProcessStateUpdateEvent), + FatalError(String), } impl From for TracerMessage { diff --git a/src/main.rs b/src/main.rs index b25b2117..fd204c8c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -138,14 +138,22 @@ async fn main() -> color_eyre::Result<()> { )?); let tracer_thread = tracer.spawn(cmd, Some(output), req_rx); loop { - if let Some(TracerMessage::Event(TracerEvent { - details: TracerEventDetails::TraceeExit { exit_code, .. }, - .. - })) = tracer_rx.recv().await - { - tracing::debug!("Waiting for tracer thread to exit"); - tracer_thread.await??; - process::exit(exit_code); + match tracer_rx.recv().await { + Some(TracerMessage::Event(TracerEvent { + details: TracerEventDetails::TraceeExit { exit_code, .. }, + .. + })) => { + tracing::debug!("Waiting for tracer thread to exit"); + tracer_thread.await??; + process::exit(exit_code); + } + // channel closed abnormally. + None | Some(TracerMessage::FatalError(_)) => { + tracing::debug!("Waiting for tracer thread to exit"); + tracer_thread.await??; + process::exit(1); + } + _ => (), } } } @@ -282,6 +290,12 @@ async fn main() -> color_eyre::Result<()> { })) => { json.events.push(JsonExecEvent::new(id, *exec)); } + // channel closed abnormally. + None | Some(TracerMessage::FatalError(_)) => { + tracing::debug!("Waiting for tracer thread to exit"); + tracer_thread.await??; + process::exit(1); + } _ => (), } } @@ -307,6 +321,12 @@ async fn main() -> color_eyre::Result<()> { output.write_all(&[b'\n'])?; output.flush()?; } + // channel closed abnormally. + None | Some(TracerMessage::FatalError(_)) => { + tracing::debug!("Waiting for tracer thread to exit"); + tracer_thread.await??; + process::exit(1); + } _ => (), } } diff --git a/src/tracer.rs b/src/tracer.rs index b9fa3b6f..f9e36cd7 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -227,10 +227,15 @@ impl Tracer { let current_thread = pthread_self(); pthread_setname_np(current_thread, "tracer\0\0\0\0\0\0\0\0\0\0".as_ptr().cast()); } - tokio::runtime::Handle::current().block_on(async move { + let tx = self.msg_tx.clone(); + let result = tokio::runtime::Handle::current().block_on(async move { self.printer.init_thread_local(output); self.run(args, req_rx).await - }) + }); + if let Err(e) = &result { + tx.send(TracerMessage::FatalError(e.to_string())).unwrap(); + } + result } }) } diff --git a/src/tui.rs b/src/tui.rs index a31d8928..eb2faf56 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -36,7 +36,7 @@ use tokio::{ use tokio_util::sync::CancellationToken; use tracing::{error, trace}; -use crate::event::{Event, TracerMessage}; +use crate::event::{Event, TracerEvent, TracerEventDetails, TracerEventMessage, TracerMessage}; pub mod app; mod breakpoint_manager; @@ -112,33 +112,42 @@ impl Tui { let crossterm_event = reader.next().fuse(); let tracer_event = tracer_rx.recv(); tokio::select! { - _ = _cancellation_token.cancelled() => { - break; - } - Some(tracer_event) = tracer_event => { - trace!("TUI event: tracer message!"); + _ = _cancellation_token.cancelled() => { + break; + } + tracer_event = tracer_event => { + trace!("TUI event: tracer message!"); + if let Some(tracer_event) = tracer_event { _event_tx.send(Event::Tracer(tracer_event)).unwrap(); + } else { + // channel closed abnormally + _event_tx.send(Event::Tracer(TracerMessage::Event(TracerEvent { + details: TracerEventDetails::Error(TracerEventMessage { + pid: None, + msg: "The connection between TUI and tracer shutdown abnormally. Tracer is probably died.".to_string() + }), id: u64::MAX }))).unwrap(); } - Some(event) = crossterm_event => { - #[cfg(debug_assertions)] - trace!("TUI event: crossterm event {event:?}!"); - match event { - Ok(evt) => { - match evt { - CrosstermEvent::Key(key) => { - if key.kind == KeyEventKind::Press { - _event_tx.send(Event::Key(key)).unwrap(); - } - }, - CrosstermEvent::Resize(cols, rows) => { - _event_tx.send(Event::Resize(Size { - width: cols, - height: rows, - })).unwrap(); - }, - _ => {}, - } + } + Some(event) = crossterm_event => { + #[cfg(debug_assertions)] + trace!("TUI event: crossterm event {event:?}!"); + match event { + Ok(evt) => { + match evt { + CrosstermEvent::Key(key) => { + if key.kind == KeyEventKind::Press { + _event_tx.send(Event::Key(key)).unwrap(); + } + }, + CrosstermEvent::Resize(cols, rows) => { + _event_tx.send(Event::Resize(Size { + width: cols, + height: rows, + })).unwrap(); + }, + _ => {}, } + } Err(_) => { _event_tx.send(Event::Error).unwrap(); } diff --git a/src/tui/app.rs b/src/tui/app.rs index 8676fbfb..6bbea4c8 100644 --- a/src/tui/app.rs +++ b/src/tui/app.rs @@ -503,6 +503,17 @@ impl App { self.event_list.update(update); } } + TracerMessage::FatalError(e) => { + action_tx.send(Action::SetActivePopup(ActivePopup::InfoPopup( + InfoPopupState::error( + "FATAL ERROR in tracer thread".to_string(), + vec![ + Line::raw("The tracer thread has died abnormally! error: "), + e.into(), + ], + ), + )))?; + } } // action_tx.send(Action::Render)?; }