Make sure starting listenvars is idempodent (fixes #360)

This commit is contained in:
elkowar 2022-08-27 10:43:51 +02:00
parent 9977384b06
commit 3ab53b0323
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
2 changed files with 15 additions and 5 deletions

View file

@ -332,7 +332,8 @@ impl App {
let mut eww_window = initialize_window(monitor_geometry, root_widget, window_def, window_scope)?; let mut eww_window = initialize_window(monitor_geometry, root_widget, window_def, window_scope)?;
eww_window.gtk_window.style_context().add_class(&window_name.to_string()); eww_window.gtk_window.style_context().add_class(&window_name.to_string());
// initialize script var handlers for variables that where not used before opening this window. // initialize script var handlers for variables. As starting a scriptvar with the script_var_handler is idempodent,
// we can just start script vars that are already running without causing issues
// TODO maybe this could be handled by having a track_newly_used_variables function in the scope tree? // TODO maybe this could be handled by having a track_newly_used_variables function in the scope tree?
for used_var in self.scope_graph.borrow().variables_used_in_self_or_subscopes_of(eww_window.scope_index) { for used_var in self.scope_graph.borrow().variables_used_in_self_or_subscopes_of(eww_window.scope_index) {
if let Ok(script_var) = self.eww_config.get_script_var(&used_var) { if let Ok(script_var) = self.eww_config.get_script_var(&used_var) {
@ -348,9 +349,8 @@ impl App {
// Generally, this should get disconnected before the gtk window gets destroyed. // Generally, this should get disconnected before the gtk window gets destroyed.
// It serves as a fallback for when the window is closed manually. // It serves as a fallback for when the window is closed manually.
let (response_sender, _) = daemon_response::create_pair(); let (response_sender, _) = daemon_response::create_pair();
if let Err(err) = app_evt_sender let command = DaemonCommand::CloseWindows { windows: vec![window_name.clone()], sender: response_sender };
.send(DaemonCommand::CloseWindows { windows: vec![window_name.clone()], sender: response_sender }) if let Err(err) = app_evt_sender.send(command) {
{
log::error!("Error sending close window command to daemon after gtk window destroy event: {}", err); log::error!("Error sending close window command to daemon after gtk window destroy event: {}", err);
} }
} }

View file

@ -61,6 +61,8 @@ pub struct ScriptVarHandlerHandle {
impl ScriptVarHandlerHandle { impl ScriptVarHandlerHandle {
/// Add a new script-var that should be executed. /// Add a new script-var that should be executed.
/// This is idempodent, meaning that running a definition that already has a script_var attached which is running
/// won't do anything.
pub fn add(&self, script_var: ScriptVarDefinition) { pub fn add(&self, script_var: ScriptVarDefinition) {
crate::print_result_err!( crate::print_result_err!(
"while forwarding instruction to script-var handler", "while forwarding instruction to script-var handler",
@ -204,8 +206,16 @@ impl ListenVarHandler {
Ok(handler) Ok(handler)
} }
/// Start a listen-var. Starting a variable that is already running will not do anything.
async fn start(&mut self, var: ListenScriptVar) { async fn start(&mut self, var: ListenScriptVar) {
log::debug!("starting listen-var {}", &var.name); log::debug!("starting listen-var {}", &var.name);
// Make sure the same listenvar is never started twice,
// as that would cause eww to not clean up the older listenvar on window close.
if self.listen_process_handles.contains_key(&var.name) {
return;
}
let cancellation_token = CancellationToken::new(); let cancellation_token = CancellationToken::new();
self.listen_process_handles.insert(var.name.clone(), cancellation_token.clone()); self.listen_process_handles.insert(var.name.clone(), cancellation_token.clone());
@ -264,7 +274,7 @@ async fn terminate_handle(mut child: tokio::process::Child) {
if let Some(id) = child.id() { if let Some(id) = child.id() {
let _ = signal::killpg(Pid::from_raw(id as i32), signal::SIGTERM); let _ = signal::killpg(Pid::from_raw(id as i32), signal::SIGTERM);
tokio::select! { tokio::select! {
_ = child.wait() => {}, _ = child.wait() => { },
_ = tokio::time::sleep(std::time::Duration::from_secs(10)) => { _ = tokio::time::sleep(std::time::Duration::from_secs(10)) => {
let _ = child.kill().await; let _ = child.kill().await;
} }