1use std::{
5 collections::BTreeSet,
6 sync::{Arc, Mutex},
7};
8
9#[derive(Default, Debug)]
10struct Inner {
11 live: BTreeSet<i32>,
12 torn_down: bool,
13}
14
15#[derive(Clone, Default, Debug)]
17pub struct ProcGroupRegistry {
18 inner: Arc<Mutex<Inner>>,
19}
20
21impl ProcGroupRegistry {
22 #[must_use]
24 pub fn new() -> Self {
25 Self::default()
26 }
27
28 #[must_use]
30 pub fn register_active(&self, process_group: i32) -> bool {
31 let mut inner = self.inner.lock().expect("process-group registry poisoned");
32 if inner.torn_down {
33 false
34 } else {
35 inner.live.insert(process_group);
36 true
37 }
38 }
39
40 pub fn unregister(&self, process_group: i32) {
42 self.inner
43 .lock()
44 .expect("process-group registry poisoned")
45 .live
46 .remove(&process_group);
47 }
48
49 #[must_use]
51 pub fn len(&self) -> usize {
52 self.inner
53 .lock()
54 .expect("process-group registry poisoned")
55 .live
56 .len()
57 }
58
59 #[must_use]
61 pub fn is_empty(&self) -> bool {
62 self.len() == 0
63 }
64
65 #[cfg(unix)]
67 pub fn kill_group(process_group: i32) {
68 unsafe {
70 libc::kill(-process_group, libc::SIGKILL);
71 }
72 }
73
74 #[cfg(not(unix))]
76 pub fn kill_group(_process_group: i32) {}
77
78 #[cfg(unix)]
80 pub fn kill_all(&self) -> usize {
81 let mut inner = self.inner.lock().expect("process-group registry poisoned");
82 let count = inner.live.len();
83 for process_group in &inner.live {
84 unsafe {
86 libc::kill(-process_group, libc::SIGKILL);
87 }
88 }
89 inner.live.clear();
90 inner.torn_down = true;
91 count
92 }
93
94 #[cfg(not(unix))]
96 pub fn kill_all(&self) -> usize {
97 let mut inner = self.inner.lock().expect("process-group registry poisoned");
98 inner.live.clear();
99 inner.torn_down = true;
100 0
101 }
102}