Skip to content

Commit de2fec0

Browse files
author
unpluggedcoder
committed
Add nix crate to improve signal handling in multi-thread application.
1 parent 170fbb9 commit de2fec0

File tree

3 files changed

+72
-32
lines changed

3 files changed

+72
-32
lines changed

Cargo.lock

Lines changed: 24 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

preload/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ lazy_static = "1"
1515
memmap = "0.7"
1616
log = "0.4"
1717
glob = "0.2"
18+
nix = "0.17"
1819
jemallocator = { path = "../jemallocator", default-features = false }
1920
jemalloc-sys = { path = "../jemallocator/jemalloc-sys", default-features = false }
2021

preload/src/init.rs

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
use nix::sys::signal;
12
use std::env;
3+
use std::thread;
4+
use std::sync::atomic::{AtomicBool, Ordering};
25

36
use crate::global::on_exit;
47
use crate::logger;
58
use crate::opt;
9+
use crate::spin_lock::SpinLock;
610
use crate::utils::generate_filename;
711

12+
static SIGNALWAIT_THREAD_HANDLE: SpinLock<Option<thread::JoinHandle<()>>> =
13+
SpinLock::new(None);
14+
815
fn initialize_logger() {
916
static mut SYSCALL_LOGGER: logger::SyscallLogger = logger::SyscallLogger::empty();
1017
static mut FILE_LOGGER: logger::FileLogger = logger::FileLogger::empty();
@@ -55,33 +62,50 @@ fn initialize_atexit_hook() {
5562
}
5663

5764
fn initialize_signal_handlers() {
58-
extern "C" fn sigusr_handler(signal: libc::c_int) {
59-
let signal_name = match signal {
60-
libc::SIGUSR1 => "SIGUSR1",
61-
libc::SIGUSR2 => "SIGUSR2",
62-
_ => "???",
63-
};
64-
65-
info!(
66-
"Signal handler triggered with signal: {} ({})",
67-
signal_name, signal
68-
);
69-
crate::global::toggle();
65+
if !opt::get().register_sigusr1 && !opt::get().register_sigusr2 {
66+
info!("Skip signal register.");
67+
return;
7068
}
71-
69+
let mut sigset = signal::SigSet::empty();
7270
if opt::get().register_sigusr1 {
71+
sigset.add(signal::Signal::SIGUSR1);
7372
info!("Registering SIGUSR1 handler...");
74-
unsafe {
75-
libc::signal(libc::SIGUSR1, sigusr_handler as libc::sighandler_t);
76-
}
7773
}
78-
7974
if opt::get().register_sigusr2 {
75+
sigset.add(signal::Signal::SIGUSR2);
8076
info!("Registering SIGUSR2 handler...");
81-
unsafe {
82-
libc::signal(libc::SIGUSR2, sigusr_handler as libc::sighandler_t);
83-
}
8477
}
78+
sigset.thread_block().expect("Register signal failed!");
79+
80+
let mut thread_handle = SIGNALWAIT_THREAD_HANDLE.lock();
81+
static SIG_THREAD_RUNNING: AtomicBool = AtomicBool::new(false);
82+
let new_handle = thread::Builder::new()
83+
.name("Sigwait".into())
84+
.spawn(move || loop {
85+
match sigset.wait() {
86+
Ok(sig) => {
87+
let signal_name = match sig {
88+
signal::Signal::SIGUSR1 => "SIGUSR1",
89+
signal::Signal::SIGUSR2 => "SIGUSR2",
90+
_ => "???",
91+
};
92+
93+
info!(
94+
"Signal handler triggered with signal: {} ({})",
95+
signal_name, sig
96+
);
97+
crate::global::toggle();
98+
}
99+
Err(e) => error!("Signal wait error: {}", e),
100+
}
101+
})
102+
.expect("Failed to start Sigwait thread");
103+
104+
while SIG_THREAD_RUNNING.load(Ordering::SeqCst) == false {
105+
thread::yield_now();
106+
}
107+
108+
*thread_handle = Some(new_handle);
85109
}
86110

87111
pub fn startup() {
@@ -93,12 +117,13 @@ pub fn startup() {
93117
}
94118

95119
initialize_atexit_hook();
120+
121+
initialize_signal_handlers();
122+
96123
if !opt::get().disabled_by_default {
97124
crate::global::toggle();
98125
}
99126

100-
initialize_signal_handlers();
101-
102127
env::remove_var("LD_PRELOAD");
103128
info!("Startup initialization finished");
104129
}

0 commit comments

Comments
 (0)