diff -r e70b616a077b -r 89742f1fa6cb rust/chg/src/procutil.rs --- a/rust/chg/src/procutil.rs Mon Sep 24 22:19:49 2018 +0900 +++ b/rust/chg/src/procutil.rs Tue Sep 25 20:55:03 2018 +0900 @@ -5,14 +5,19 @@ //! Low-level utility for signal and process handling. -use libc::{self, c_int, size_t, ssize_t}; +use libc::{self, c_int, pid_t, size_t, ssize_t}; use std::io; use std::os::unix::io::RawFd; +use std::sync; #[link(name = "procutil", kind = "static")] extern "C" { // sendfds.c fn sendfds(sockfd: c_int, fds: *const c_int, fdlen: size_t) -> ssize_t; + + // sighandlers.c + fn setupsignalhandler(pid: pid_t, pgid: pid_t) -> c_int; + fn restoresignalhandler() -> c_int; } /// Returns the effective uid of the current process. @@ -41,3 +46,42 @@ } Ok(()) } + +static SETUP_SIGNAL_HANDLER: sync::Once = sync::Once::new(); +static RESTORE_SIGNAL_HANDLER: sync::Once = sync::Once::new(); + +/// Installs signal handlers to forward signals to the server. +/// +/// # Safety +/// +/// This touches global states, and thus synchronized as a one-time +/// initialization function. +pub fn setup_signal_handler_once(pid: u32, pgid: Option) -> io::Result<()> { + let pid_signed = pid as i32; + let pgid_signed = pgid.map(|n| n as i32).unwrap_or(0); + let mut r = 0; + SETUP_SIGNAL_HANDLER.call_once(|| { + r = unsafe { setupsignalhandler(pid_signed, pgid_signed) }; + }); + if r < 0 { + return Err(io::Error::last_os_error()); + } + Ok(()) +} + +/// Restores the original signal handlers. +/// +/// # Safety +/// +/// This touches global states, and thus synchronized as a one-time +/// initialization function. +pub fn restore_signal_handler_once() -> io::Result<()> { + let mut r = 0; + RESTORE_SIGNAL_HANDLER.call_once(|| { + r = unsafe { restoresignalhandler() }; + }); + if r < 0 { + return Err(io::Error::last_os_error()); + } + Ok(()) +}