rust_shell/
process_manager.rs1use libc::c_int;
16use libc;
17use libc::sigset_t;
18use std::sync::Arc;
19use std::sync::Mutex;
20use std::thread::ThreadId;
21use local_shell::LocalShell;
22use std::collections::HashMap;
23use result::check_errno;
24use result::ShellError;
25use std::mem;
26use errno::Errno;
27use std::thread;
28
29pub struct ProcessManager {
31 children: HashMap<ThreadId, Arc<Mutex<LocalShell>>>
32}
33
34impl ProcessManager {
35 fn new() -> ProcessManager {
36 ProcessManager {
37 children: HashMap::new()
38 }
39 }
40
41 pub fn add_local_shell(&mut self, id: &ThreadId,
42 shell: &Arc<Mutex<LocalShell>>) {
43 self.children.insert(id.clone(), shell.clone());
44 }
45
46 pub fn remove_local_shell(&mut self, id: &ThreadId) {
47 self.children.remove(id);
48 }
49}
50
51#[allow(dead_code)]
57pub fn trap_signal_and_wait_children() -> Result<(), ShellError> {
58 unsafe {
59 let mut sigset = mem::uninitialized::<sigset_t>();
60 check_errno("sigemptyset",
61 libc::sigemptyset(&mut sigset as *mut sigset_t))?;
62 check_errno("sigaddset", libc::sigaddset(
63 &mut sigset as *mut sigset_t, libc::SIGINT))?;
64 check_errno("sigaddset", libc::sigaddset(
65 &mut sigset as *mut sigset_t, libc::SIGTERM))?;
66
67 let mut oldset = mem::uninitialized::<sigset_t>();
68 let result = libc::pthread_sigmask(
69 libc::SIG_BLOCK, &mut sigset as *mut sigset_t,
70 &mut oldset as *mut sigset_t);
71 if result != 0 {
72 return Err(ShellError::Errno("pthread_sigmask", Errno(result)));
73 }
74
75 thread::spawn(move || {
76 info!("Start waitinig signal");
77 let mut signal: c_int = 0;
78 let result = libc::sigwait(
79 &sigset as *const sigset_t, &mut signal as *mut c_int);
80 if result != 0 {
81 eprintln!("sigwait failed {}", result);
82 return;
83 }
84 info!("Signal {} is received", signal);
85 let mut lock = PROCESS_MANAGER.lock().unwrap();
86 let mut children = lock.children.drain().collect::<Vec<_>>();
87 info!("Wait for {} child processes exiting", children.len());
88 for &mut (_, ref entry) in &mut children {
89 let mut lock = entry.lock().unwrap();
90 lock.wait();
91 }
92 ::std::process::exit(128 + signal);
93 });
94 Ok(())
95 }
96}
97
98lazy_static! {
99 pub static ref PROCESS_MANAGER: Mutex<ProcessManager> =
100 Mutex::new(ProcessManager::new());
101}