gardesk/gar / fe6b01b

Browse files

kill spawned children on exit: use process groups

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
fe6b01bfe55eae5d69d942eacb8ff096fd8b9a60
Parents
bb19a9d
Tree
d975960

1 changed file

StatusFile+-
M gar/src/config/lua.rs 11 2
gar/src/config/lua.rsmodified
@@ -1,4 +1,5 @@
1
 use std::collections::HashSet;
1
 use std::collections::HashSet;
2
+use std::os::unix::process::CommandExt;
2
 use std::path::PathBuf;
3
 use std::path::PathBuf;
3
 use std::sync::{Arc, Mutex};
4
 use std::sync::{Arc, Mutex};
4
 
5
 
@@ -95,8 +96,10 @@ impl LuaState {
95
             // SAFETY: Sending signal 0 just checks if process exists
96
             // SAFETY: Sending signal 0 just checks if process exists
96
             let exists = unsafe { libc::kill(pid as i32, 0) == 0 };
97
             let exists = unsafe { libc::kill(pid as i32, 0) == 0 };
97
             if exists {
98
             if exists {
98
-                tracing::debug!("Sending SIGTERM to PID {}", pid);
99
+                // Kill the entire process group (negative PID) to get children too
99
-                unsafe { libc::kill(pid as i32, libc::SIGTERM); }
100
+                // This handles cases like "sh -c garterm" where sh spawns garterm
101
+                tracing::debug!("Sending SIGTERM to process group {}", pid);
102
+                unsafe { libc::kill(-(pid as i32), libc::SIGTERM); }
100
             }
103
             }
101
         }
104
         }
102
     }
105
     }
@@ -643,9 +646,12 @@ impl LuaConfig {
643
         let state = Arc::clone(&self.state);
646
         let state = Arc::clone(&self.state);
644
         let exec_fn = self.lua.create_function(move |_, cmd: String| {
647
         let exec_fn = self.lua.create_function(move |_, cmd: String| {
645
             tracing::debug!("exec: {}", cmd);
648
             tracing::debug!("exec: {}", cmd);
649
+            // process_group(0) makes the child its own process group leader
650
+            // so we can kill the entire group (including grandchildren) on exit
646
             if let Ok(child) = std::process::Command::new("sh")
651
             if let Ok(child) = std::process::Command::new("sh")
647
                 .arg("-c")
652
                 .arg("-c")
648
                 .arg(&cmd)
653
                 .arg(&cmd)
654
+                .process_group(0)
649
                 .spawn()
655
                 .spawn()
650
             {
656
             {
651
                 let pid = child.id();
657
                 let pid = child.id();
@@ -669,9 +675,12 @@ impl LuaConfig {
669
                 }
675
                 }
670
             }
676
             }
671
             tracing::info!("exec_once: {}", cmd);
677
             tracing::info!("exec_once: {}", cmd);
678
+            // process_group(0) makes the child its own process group leader
679
+            // so we can kill the entire group (including grandchildren) on exit
672
             if let Ok(child) = std::process::Command::new("sh")
680
             if let Ok(child) = std::process::Command::new("sh")
673
                 .arg("-c")
681
                 .arg("-c")
674
                 .arg(&cmd)
682
                 .arg(&cmd)
683
+                .process_group(0)
675
                 .spawn()
684
                 .spawn()
676
             {
685
             {
677
                 let pid = child.id();
686
                 let pid = child.id();