##// END OF EJS Templates
rust-chg: install signal handlers to forward signals to server...
Yuya Nishihara -
r40156:89742f1f default
parent child Browse files
Show More
@@ -10,6 +10,7 b' extern crate tokio_hglib;'
10 10
11 11 use chg::{ChgClientExt, ChgUiHandler};
12 12 use chg::locator;
13 use chg::procutil;
13 14 use futures::sync::oneshot;
14 15 use std::env;
15 16 use std::io;
@@ -38,9 +39,16 b' fn run() -> io::Result<i32> {'
38 39 client.attach_io(io::stdin(), io::stdout(), io::stderr())
39 40 })
40 41 .and_then(|client| {
42 let pid = client.server_spec().process_id.unwrap();
43 let pgid = client.server_spec().process_group_id;
44 procutil::setup_signal_handler_once(pid, pgid)?;
45 Ok(client)
46 })
47 .and_then(|client| {
41 48 client.run_command_chg(handler, env::args_os().skip(1))
42 49 })
43 50 .map(|(_client, _handler, code)| {
51 procutil::restore_signal_handler_once()?;
44 52 Ok(code)
45 53 })
46 54 .or_else(|err| Ok(Err(err))) // pass back error to caller
@@ -5,14 +5,19 b''
5 5
6 6 //! Low-level utility for signal and process handling.
7 7
8 use libc::{self, c_int, size_t, ssize_t};
8 use libc::{self, c_int, pid_t, size_t, ssize_t};
9 9 use std::io;
10 10 use std::os::unix::io::RawFd;
11 use std::sync;
11 12
12 13 #[link(name = "procutil", kind = "static")]
13 14 extern "C" {
14 15 // sendfds.c
15 16 fn sendfds(sockfd: c_int, fds: *const c_int, fdlen: size_t) -> ssize_t;
17
18 // sighandlers.c
19 fn setupsignalhandler(pid: pid_t, pgid: pid_t) -> c_int;
20 fn restoresignalhandler() -> c_int;
16 21 }
17 22
18 23 /// Returns the effective uid of the current process.
@@ -41,3 +46,42 b' pub fn send_raw_fds(sock_fd: RawFd, fds:'
41 46 }
42 47 Ok(())
43 48 }
49
50 static SETUP_SIGNAL_HANDLER: sync::Once = sync::Once::new();
51 static RESTORE_SIGNAL_HANDLER: sync::Once = sync::Once::new();
52
53 /// Installs signal handlers to forward signals to the server.
54 ///
55 /// # Safety
56 ///
57 /// This touches global states, and thus synchronized as a one-time
58 /// initialization function.
59 pub fn setup_signal_handler_once(pid: u32, pgid: Option<u32>) -> io::Result<()> {
60 let pid_signed = pid as i32;
61 let pgid_signed = pgid.map(|n| n as i32).unwrap_or(0);
62 let mut r = 0;
63 SETUP_SIGNAL_HANDLER.call_once(|| {
64 r = unsafe { setupsignalhandler(pid_signed, pgid_signed) };
65 });
66 if r < 0 {
67 return Err(io::Error::last_os_error());
68 }
69 Ok(())
70 }
71
72 /// Restores the original signal handlers.
73 ///
74 /// # Safety
75 ///
76 /// This touches global states, and thus synchronized as a one-time
77 /// initialization function.
78 pub fn restore_signal_handler_once() -> io::Result<()> {
79 let mut r = 0;
80 RESTORE_SIGNAL_HANDLER.call_once(|| {
81 r = unsafe { restoresignalhandler() };
82 });
83 if r < 0 {
84 return Err(io::Error::last_os_error());
85 }
86 Ok(())
87 }
General Comments 0
You need to be logged in to leave comments. Login now