Skip to content

Commit f566c77

Browse files
Added signal library
Register a signal handler with signal, ignore, or default. Send a signal with kill.
1 parent d4fb7d1 commit f566c77

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/target/
2+
**/*.rs.bk
3+
Cargo.lock
4+
**/*.iml
5+
**/*.idea

Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "signal"
3+
version = "0.1.0"
4+
authors = ["Michael Micucci <[email protected]>"]
5+
6+
[dependencies]
7+
libc = "*"

src/lib.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
extern crate libc;
2+
3+
use std::mem::{transmute, uninitialized};
4+
5+
pub use libc::{SIGINT, SIGTERM, SIGUSR1, SIGUSR2};
6+
pub use libc::{SIGHUP, SIGQUIT, SIGPIPE, SIGALRM, SIGTRAP};
7+
pub use libc::c_int as int;
8+
9+
pub fn signal(signum: int, sig_handler: fn(int), flags: Option<int>) {
10+
let int_sig_handler: libc::size_t = unsafe { transmute(sig_handler) };
11+
signal_internal(signum, int_sig_handler, flags)
12+
}
13+
14+
fn signal_internal(signum: int, sig_handler: libc::size_t, flags: Option<int>) {
15+
let mut sigset: libc::sigset_t = unsafe { uninitialized() };
16+
let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };
17+
18+
let mut siga = unsafe { uninitialized::<libc::sigaction>() };
19+
let mut oldact = unsafe { uninitialized::<libc::sigaction>() };
20+
21+
siga.sa_sigaction = sig_handler;
22+
siga.sa_mask = sigset;
23+
siga.sa_flags = flags.map(|x| { x - libc::SA_SIGINFO }).unwrap_or(libc::SA_ONSTACK | libc::SA_RESTART);
24+
siga.sa_restorer = None;
25+
26+
unsafe { libc::sigaction(signum, &siga as *const libc::sigaction, &mut oldact as *mut libc::sigaction) };
27+
}
28+
29+
pub fn default(signum: int) {
30+
let int_sig_handler: libc::size_t = unsafe { transmute(libc::SIG_DFL) };
31+
signal_internal(signum, int_sig_handler, None)
32+
}
33+
34+
pub fn ignore(signum: int) {
35+
let int_sig_handler: libc::size_t = unsafe { transmute(libc::SIG_IGN) };
36+
signal_internal(signum, int_sig_handler, None)
37+
}
38+
39+
pub fn kill(signal: int) {
40+
unsafe { libc::kill(libc::getpid(), signal) };
41+
}
42+
43+
#[cfg(test)]
44+
mod tests {
45+
use super::*;
46+
47+
static mut HANDLER_RUN:u32 = 0;
48+
49+
fn test_handler(_: int) {
50+
println!("Handler running!");
51+
unsafe { HANDLER_RUN = HANDLER_RUN + 1 };
52+
}
53+
54+
#[test]
55+
fn test_signals() {
56+
signal(SIGUSR1, test_handler, None);
57+
58+
kill(SIGUSR1);
59+
::std::thread::sleep(::std::time::Duration::from_secs(1));
60+
unsafe { assert_eq!(HANDLER_RUN, 1) } ;
61+
62+
default(SIGUSR1);
63+
64+
ignore(SIGUSR1);
65+
66+
kill(SIGUSR1);
67+
::std::thread::sleep(::std::time::Duration::from_secs(1));
68+
69+
signal(SIGUSR1, test_handler, None);
70+
signal(SIGUSR2, test_handler, None);
71+
72+
kill(SIGUSR1);
73+
::std::thread::sleep(::std::time::Duration::from_secs(1));
74+
unsafe { assert_eq!(HANDLER_RUN, 2) } ;
75+
76+
kill(SIGUSR2);
77+
::std::thread::sleep(::std::time::Duration::from_secs(2));
78+
unsafe { assert_eq!(HANDLER_RUN, 3) } ;
79+
}
80+
81+
}

0 commit comments

Comments
 (0)