Skip to content

Commit c00e905

Browse files
Add nix crate to improve signal handling in multi-thread application.
1 parent b3ae011 commit c00e905

3 files changed

Lines changed: 75 additions & 45 deletions

File tree

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: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use nix::sys::signal;
12
use std::env;
23

34
use crate::global::on_exit;
@@ -8,80 +9,94 @@ use crate::utils::generate_filename;
89
fn initialize_logger() {
910
static mut SYSCALL_LOGGER: logger::SyscallLogger = logger::SyscallLogger::empty();
1011
static mut FILE_LOGGER: logger::FileLogger = logger::FileLogger::empty();
11-
let log_level = if let Ok( value ) = env::var( "MEMORY_PROFILER_LOG" ) {
12+
let log_level = if let Ok(value) = env::var("MEMORY_PROFILER_LOG") {
1213
match value.as_str() {
1314
"trace" => log::LevelFilter::Trace,
1415
"debug" => log::LevelFilter::Debug,
1516
"info" => log::LevelFilter::Info,
1617
"warn" => log::LevelFilter::Warn,
1718
"error" => log::LevelFilter::Error,
18-
_ => log::LevelFilter::Off
19+
_ => log::LevelFilter::Off,
1920
}
2021
} else {
2122
log::LevelFilter::Off
2223
};
2324

2425
let pid = unsafe { libc::getpid() };
2526

26-
if let Ok( value ) = env::var( "MEMORY_PROFILER_LOGFILE" ) {
27-
let path = generate_filename( &value, None );
28-
let rotate_at = env::var( "MEMORY_PROFILER_LOGFILE_ROTATE_WHEN_BIGGER_THAN" ).ok().and_then( |value| value.parse().ok() );
27+
if let Ok(value) = env::var("MEMORY_PROFILER_LOGFILE") {
28+
let path = generate_filename(&value, None);
29+
let rotate_at = env::var("MEMORY_PROFILER_LOGFILE_ROTATE_WHEN_BIGGER_THAN")
30+
.ok()
31+
.and_then(|value| value.parse().ok());
2932

3033
unsafe {
31-
if let Ok(()) = FILE_LOGGER.initialize( path, rotate_at, log_level, pid ) {
32-
log::set_logger( &FILE_LOGGER ).unwrap();
34+
if let Ok(()) = FILE_LOGGER.initialize(path, rotate_at, log_level, pid) {
35+
log::set_logger(&FILE_LOGGER).unwrap();
3336
}
3437
}
3538
} else {
3639
unsafe {
37-
SYSCALL_LOGGER.initialize( log_level, pid );
38-
log::set_logger( &SYSCALL_LOGGER ).unwrap();
40+
SYSCALL_LOGGER.initialize(log_level, pid);
41+
log::set_logger(&SYSCALL_LOGGER).unwrap();
3942
}
4043
}
4144

42-
log::set_max_level( log_level );
45+
log::set_max_level(log_level);
4346
}
4447

4548
fn initialize_atexit_hook() {
46-
info!( "Setting atexit hook..." );
49+
info!("Setting atexit hook...");
4750
unsafe {
48-
let result = libc::atexit( on_exit );
51+
let result = libc::atexit(on_exit);
4952
if result != 0 {
50-
error!( "Cannot set the at-exit hook" );
53+
error!("Cannot set the at-exit hook");
5154
}
5255
}
5356
}
5457

5558
fn initialize_signal_handlers() {
56-
extern "C" fn sigusr_handler( signal: libc::c_int ) {
57-
let signal_name = match signal {
58-
libc::SIGUSR1 => "SIGUSR1",
59-
libc::SIGUSR2 => "SIGUSR2",
60-
_ => "???"
61-
};
62-
63-
info!( "Signal handler triggered with signal: {} ({})", signal_name, signal );
64-
crate::global::toggle();
59+
if !opt::get().register_sigusr1 && !opt::get().register_sigusr2 {
60+
info!("Skip signal register.");
61+
return;
6562
}
66-
63+
let mut sigset = signal::SigSet::empty();
6764
if opt::get().register_sigusr1 {
68-
info!( "Registering SIGUSR1 handler..." );
69-
unsafe {
70-
libc::signal( libc::SIGUSR1, sigusr_handler as libc::sighandler_t );
71-
}
65+
sigset.add(signal::Signal::SIGUSR1);
66+
info!("Registering SIGUSR1 handler...");
7267
}
73-
7468
if opt::get().register_sigusr2 {
75-
info!( "Registering SIGUSR2 handler..." );
76-
unsafe {
77-
libc::signal( libc::SIGUSR2, sigusr_handler as libc::sighandler_t );
78-
}
69+
sigset.add(signal::Signal::SIGUSR2);
70+
info!("Registering SIGUSR2 handler...");
7971
}
72+
sigset.thread_block().expect("Register signal failed!");
73+
74+
thread::Builder::new()
75+
.name("Sigwait".into())
76+
.spawn(move || loop {
77+
match sigset.wait() {
78+
Ok(sig) => {
79+
let signal_name = match sig {
80+
signal::Signal::SIGUSR1 => "SIGUSR1",
81+
signal::Signal::SIGUSR2 => "SIGUSR2",
82+
_ => "???",
83+
};
84+
85+
info!(
86+
"Signal handler triggered with signal: {} ({})",
87+
signal_name, sig
88+
);
89+
crate::global::toggle();
90+
}
91+
Err(e) => error!("Signal wait error: {}", e),
92+
}
93+
})
94+
.expect("Failed to start Sigwait thread");
8095
}
8196

8297
pub fn startup() {
8398
initialize_logger();
84-
info!( "Version: {}", env!( "CARGO_PKG_VERSION" ) );
99+
info!("Version: {}", env!("CARGO_PKG_VERSION"));
85100

86101
unsafe {
87102
opt::initialize();
@@ -94,6 +109,6 @@ pub fn startup() {
94109

95110
initialize_signal_handlers();
96111

97-
env::remove_var( "LD_PRELOAD" );
98-
info!( "Startup initialization finished" );
112+
env::remove_var("LD_PRELOAD");
113+
info!("Startup initialization finished");
99114
}

0 commit comments

Comments
 (0)