##// 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 extern crate tokio_hglib;
10
10
11 use chg::{ChgClientExt, ChgUiHandler};
11 use chg::{ChgClientExt, ChgUiHandler};
12 use chg::locator;
12 use chg::locator;
13 use chg::procutil;
13 use futures::sync::oneshot;
14 use futures::sync::oneshot;
14 use std::env;
15 use std::env;
15 use std::io;
16 use std::io;
@@ -38,9 +39,16 fn run() -> io::Result<i32> {
38 client.attach_io(io::stdin(), io::stdout(), io::stderr())
39 client.attach_io(io::stdin(), io::stdout(), io::stderr())
39 })
40 })
40 .and_then(|client| {
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 client.run_command_chg(handler, env::args_os().skip(1))
48 client.run_command_chg(handler, env::args_os().skip(1))
42 })
49 })
43 .map(|(_client, _handler, code)| {
50 .map(|(_client, _handler, code)| {
51 procutil::restore_signal_handler_once()?;
44 Ok(code)
52 Ok(code)
45 })
53 })
46 .or_else(|err| Ok(Err(err))) // pass back error to caller
54 .or_else(|err| Ok(Err(err))) // pass back error to caller
@@ -5,14 +5,19
5
5
6 //! Low-level utility for signal and process handling.
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 use std::io;
9 use std::io;
10 use std::os::unix::io::RawFd;
10 use std::os::unix::io::RawFd;
11 use std::sync;
11
12
12 #[link(name = "procutil", kind = "static")]
13 #[link(name = "procutil", kind = "static")]
13 extern "C" {
14 extern "C" {
14 // sendfds.c
15 // sendfds.c
15 fn sendfds(sockfd: c_int, fds: *const c_int, fdlen: size_t) -> ssize_t;
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 /// Returns the effective uid of the current process.
23 /// Returns the effective uid of the current process.
@@ -41,3 +46,42 pub fn send_raw_fds(sock_fd: RawFd, fds:
41 }
46 }
42 Ok(())
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