From ec7f982bdf253169580ad794bcac493232500b2e Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Mon, 29 Aug 2022 11:10:25 +0200 Subject: [PATCH] Add names to threads and tasks for easier debugging of crashes --- crates/eww/src/main.rs | 6 ++- crates/eww/src/script_var_handler.rs | 64 ++++++++++++++-------------- crates/eww/src/server.rs | 62 +++++++++++++++------------ crates/eww/src/widgets/mod.rs | 37 ++++++++-------- 4 files changed, 91 insertions(+), 78 deletions(-) diff --git a/crates/eww/src/main.rs b/crates/eww/src/main.rs index 74bfe3e..8f09502 100644 --- a/crates/eww/src/main.rs +++ b/crates/eww/src/main.rs @@ -144,7 +144,11 @@ fn main() { } fn listen_for_daemon_response(mut recv: DaemonResponseReceiver) { - let rt = tokio::runtime::Builder::new_current_thread().enable_time().build().expect("Failed to initialize tokio runtime"); + let rt = tokio::runtime::Builder::new_current_thread() + .thread_name("listen-for-daemon-response") + .enable_all() + .build() + .expect("Failed to initialize tokio runtime"); rt.block_on(async { if let Ok(Some(response)) = tokio::time::timeout(Duration::from_millis(100), recv.recv()).await { println!("{}", response); diff --git a/crates/eww/src/script_var_handler.rs b/crates/eww/src/script_var_handler.rs index fde341e..f5b8bd7 100644 --- a/crates/eww/src/script_var_handler.rs +++ b/crates/eww/src/script_var_handler.rs @@ -24,32 +24,39 @@ use yuck::config::script_var_definition::{ListenScriptVar, PollScriptVar, Script /// the script var execution. pub fn init(evt_send: UnboundedSender) -> ScriptVarHandlerHandle { let (msg_send, mut msg_recv) = tokio::sync::mpsc::unbounded_channel(); - let thread_handle = std::thread::spawn(move || { - let rt = tokio::runtime::Runtime::new().expect("Failed to initialize tokio runtime for script var handlers"); - rt.block_on(async { - let _: Result<_> = try { - let mut handler = ScriptVarHandler { - listen_handler: ListenVarHandler::new(evt_send.clone())?, - poll_handler: PollVarHandler::new(evt_send)?, + let thread_handle = std::thread::Builder::new() + .name("outer-script-var-handler".to_string()) + .spawn(move || { + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .thread_name("script-var-handler") + .build() + .expect("Failed to initialize tokio runtime for script var handlers"); + rt.block_on(async { + let _: Result<_> = try { + let mut handler = ScriptVarHandler { + listen_handler: ListenVarHandler::new(evt_send.clone())?, + poll_handler: PollVarHandler::new(evt_send)?, + }; + crate::loop_select_exiting! { + Some(msg) = msg_recv.recv() => match msg { + ScriptVarHandlerMsg::AddVar(var) => { + handler.add(var).await; + } + ScriptVarHandlerMsg::Stop(name) => { + handler.stop_for_variable(&name).await?; + } + ScriptVarHandlerMsg::StopAll => { + handler.stop_all().await; + break; + } + }, + else => break, + }; }; - crate::loop_select_exiting! { - Some(msg) = msg_recv.recv() => match msg { - ScriptVarHandlerMsg::AddVar(var) => { - handler.add(var).await; - } - ScriptVarHandlerMsg::Stop(name) => { - handler.stop_for_variable(&name).await?; - } - ScriptVarHandlerMsg::StopAll => { - handler.stop_all().await; - break; - } - }, - else => break, - }; - }; + }) }) - }); + .expect("Failed to start script-var-handler thread"); let handle = ScriptVarHandlerHandle { msg_send, thread_handle }; handle } @@ -279,15 +286,6 @@ impl ListenVarHandler { } } -impl Drop for ListenVarHandler { - fn drop(&mut self) { - let rt = tokio::runtime::Runtime::new().expect("Failed to initialize tokio runtime for script var handlers"); - rt.block_on(async { - self.stop_all().await; - }); - } -} - async fn terminate_handle(mut child: tokio::process::Child) { if let Some(id) = child.id() { log::debug!("Killing process with id {}", id); diff --git a/crates/eww/src/server.rs b/crates/eww/src/server.rs index 9920dcb..ba9706b 100644 --- a/crates/eww/src/server.rs +++ b/crates/eww/src/server.rs @@ -116,38 +116,46 @@ pub fn initialize_server(paths: EwwPaths, action: Option, should_ } fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender) { - std::thread::spawn(move || { - let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().expect("Failed to initialize tokio runtime"); - rt.block_on(async { - let filewatch_join_handle = { - let ui_send = ui_send.clone(); - let paths = paths.clone(); - tokio::spawn(async move { run_filewatch(paths.config_dir, ui_send).await }) - }; + std::thread::Builder::new() + .name("outer-main-async-runtime".to_string()) + .spawn(move || { + let rt = tokio::runtime::Builder::new_multi_thread() + .thread_name("main-async-runtime") + .enable_all() + .build() + .expect("Failed to initialize tokio runtime"); - let ipc_server_join_handle = { - let ui_send = ui_send.clone(); - tokio::spawn(async move { ipc_server::run_server(ui_send, paths.get_ipc_socket_file()).await }) - }; + rt.block_on(async { + let filewatch_join_handle = { + let ui_send = ui_send.clone(); + let paths = paths.clone(); + tokio::spawn(async move { run_filewatch(paths.config_dir, ui_send).await }) + }; - let forward_exit_to_app_handle = { - let ui_send = ui_send.clone(); - tokio::spawn(async move { - // Wait for application exit event - let _ = crate::application_lifecycle::recv_exit().await; - log::debug!("Forward task received exit event"); - // Then forward that to the application - let _ = ui_send.send(app::DaemonCommand::KillServer); - }) - }; + let ipc_server_join_handle = { + let ui_send = ui_send.clone(); + tokio::spawn(async move { ipc_server::run_server(ui_send, paths.get_ipc_socket_file()).await }) + }; - let result = tokio::try_join!(filewatch_join_handle, ipc_server_join_handle, forward_exit_to_app_handle); + let forward_exit_to_app_handle = { + let ui_send = ui_send.clone(); + tokio::spawn(async move { + // Wait for application exit event + let _ = crate::application_lifecycle::recv_exit().await; + log::debug!("Forward task received exit event"); + // Then forward that to the application + let _ = ui_send.send(app::DaemonCommand::KillServer); + }) + }; - if let Err(e) = result { - log::error!("Eww exiting with error: {:?}", e); - } + let result = tokio::try_join!(filewatch_join_handle, ipc_server_join_handle, forward_exit_to_app_handle); + + if let Err(e) = result { + log::error!("Eww exiting with error: {:?}", e); + } + }) }) - }); + .expect("Failed to start outer-main-async-runtime thread"); } /// Watch configuration files for changes, sending reload events to the eww app when the files change. diff --git a/crates/eww/src/widgets/mod.rs b/crates/eww/src/widgets/mod.rs index 5600885..392212f 100644 --- a/crates/eww/src/widgets/mod.rs +++ b/crates/eww/src/widgets/mod.rs @@ -17,23 +17,26 @@ where { use wait_timeout::ChildExt; let cmd = replace_placeholders(cmd, args); - std::thread::spawn(move || { - log::debug!("Running command from widget: {}", cmd); - let child = Command::new("/bin/sh").arg("-c").arg(&cmd).spawn(); - match child { - Ok(mut child) => match child.wait_timeout(timeout) { - // child timed out - Ok(None) => { - log::error!("WARNING: command {} timed out", &cmd); - let _ = child.kill(); - let _ = child.wait(); - } - Err(err) => log::error!("Failed to execute command {}: {}", cmd, err), - Ok(Some(_)) => {} - }, - Err(err) => log::error!("Failed to launch child process: {}", err), - } - }); + std::thread::Builder::new() + .name("command-execution-thread".to_string()) + .spawn(move || { + log::debug!("Running command from widget: {}", cmd); + let child = Command::new("/bin/sh").arg("-c").arg(&cmd).spawn(); + match child { + Ok(mut child) => match child.wait_timeout(timeout) { + // child timed out + Ok(None) => { + log::error!("WARNING: command {} timed out", &cmd); + let _ = child.kill(); + let _ = child.wait(); + } + Err(err) => log::error!("Failed to execute command {}: {}", cmd, err), + Ok(Some(_)) => {} + }, + Err(err) => log::error!("Failed to launch child process: {}", err), + } + }) + .expect("Failed to start command-execution-thread"); } fn replace_placeholders(cmd: &str, args: &[T]) -> String