Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use correct types and block all incoming signals if a signal handler is running. #4

Merged
merged 5 commits into from
Jul 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
[package]
name = "sig"
version = "0.1.1"
version = "1.0.0"
authors = ["adjivas <[email protected]>"]
description = "ffi library of signal(2) and kill(2)"
license = "MIT OR Apache-2.0"
documentation = "http://adjivas.github.io/sig/sig"
repository = "https://github.com/adjivas/sig"
readme = "README.md"
keywords = ["kill", "signal"]

[dependencies]
libc = "0.2"
2 changes: 1 addition & 1 deletion examples/usr1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#[macro_use]
extern crate sig;

fn event(sig: i32) {
unsafe extern "C" fn event(sig: i32) {
println!("{} was intercepted", sig);
}

Expand Down
77 changes: 35 additions & 42 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,40 @@
// This file may not be copied, modified, or distributed
// except according to those terms.

#[repr(C)]
#[derive(Copy, Clone)]
pub enum Sig {
HUP = 1, // Hangup (POSIX).
INT = 2, // Interrupt (ANSI).
QUIT = 3, // Quit (POSIX).
ILL = 4, // Illegal instruction (ANSI).
TRAP = 5, // Trace trap (POSIX).
IOT = 6, // Abort (POSIX).
BUS = 7, // IOT trap (4.2 BSD).
FPE = 8, // BUS error (4.2 BSD).
KILL = 9, // Kill, unblockable (POSIX).
USR1 = 10, // User-defined signal 1 (POSIX).
SEGV = 11, // Segmentation violation (ANSI).
USR2 = 12, // User-defined signal 2 (POSIX).
PIPE = 13, // Broken pipe (POSIX).
ALRM = 14, // Alarm clock (POSIX).
TERM = 15, // Termination (ANSI).
STKFLT = 16, // Stack fault.
CHLD = 17, // Child status has changed (POSIX).
CONT = 18, // Continue (POSIX).
STOP = 19, // Stop, unblockable (POSIX).
TSTP = 20, // Keyboard stop (POSIX).
TTIN = 21, // Background read from tty (POSIX).
TTOU = 22, // Background write to tttty (POSIX).
URG = 23, // Urgent condition on socket (4.2 BSD).
XCPU = 24, // CPU limit exceeded (4.2 BSD).
XFS2 = 25, // File size limit exceeded (4.2 BSD).
VTALRM = 26, // Virtual alarm clock (4.2 BSD).
PROF = 27, // Profiling alarm clock (4.2 BSD).
WINCH = 28, // Window size change (4.3 BSD, Sun).
POLL = 29, // Pollable event occured (System V).
PWR = 30, // Power failure restart (System V).
SYS = 31, // Bad system call.
RTMIN = 32,
RTMAX = 64,
}
pub use libc::{pid_t, c_int, getpid, kill};

#[allow(non_snake_case)]
pub mod Sig {
use libc::{self, c_int};

#[allow(improper_ctypes)]
extern "C" {
pub fn signal(sig: i32, handler: fn(i32)) -> fn(i32);
pub fn kill(pid: i32, sig: i32) -> i32;
pub fn getpid() -> i32;
pub const HUP : c_int = libc::SIGHUP; // Hangup (POSIX).
pub const INT : c_int = libc::SIGINT; // Interrupt (ANSI).
pub const QUIT : c_int = libc::SIGQUIT; // Quit (POSIX).
pub const ILL : c_int = libc::SIGILL; // Illegal instruction (ANSI).
pub const TRAP : c_int = libc::SIGTRAP; // Trace trap (POSIX).
pub const ABRT : c_int = libc::SIGABRT; // Abort (POSIX).
pub const IOT : c_int = libc::SIGIOT; // IOT trap (4.2 BSD).
pub const BUS : c_int = libc::SIGBUS; // BUS error (4.2 BSD).
pub const FPE : c_int = libc::SIGFPE;
pub const KILL : c_int = libc::SIGKILL; // Kill unblockable (POSIX).
pub const USR1 : c_int = libc::SIGUSR1; // User-defined signal 1 (POSIX).
pub const SEGV : c_int = libc::SIGSEGV; // Segmentation violation (ANSI).
pub const USR2 : c_int = libc::SIGUSR2; // User-defined signal 2 (POSIX).
pub const PIPE : c_int = libc::SIGPIPE; // Broken pipe (POSIX).
pub const ALRM : c_int = libc::SIGALRM; // Alarm clock (POSIX).
pub const TERM : c_int = libc::SIGTERM; // Termination (ANSI).
pub const STKFLT : c_int = libc::SIGSTKFLT; // Stack fault.
pub const CHLD : c_int = libc::SIGCHLD; // Child status has changed (POSIX).
pub const CONT : c_int = libc::SIGCONT; // Continue (POSIX).
pub const STOP : c_int = libc::SIGSTOP; // Stop unblockable (POSIX).
pub const TSTP : c_int = libc::SIGTSTP; // Keyboard stop (POSIX).
pub const TTIN : c_int = libc::SIGTTIN; // Background read from tty (POSIX).
pub const TTOU : c_int = libc::SIGTTOU; // Background write to tttty (POSIX).
pub const URG : c_int = libc::SIGURG; // Urgent condition on socket (4.2 BSD).
pub const XCPU : c_int = libc::SIGXCPU; // CPU limit exceeded (4.2 BSD).
pub const PROF : c_int = libc::SIGPROF; // Profiling alarm clock (4.2 BSD).
pub const WINCH : c_int = libc::SIGWINCH; // Window size change (4.3 BSD Sun).
pub const POLL : c_int = libc::SIGPOLL; // Pollable event occured (System V).
pub const PWR : c_int = libc::SIGPWR; // Power failure restart (System V).
pub const SYS : c_int = libc::SIGSYS; // Bad system call.
}
29 changes: 29 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,35 @@
//! [circle-badge]: https://circleci.com/gh/adjivas/sig/tree/master.svg?style=svg
//! [circle]: https://circleci.com/gh/adjivas/sig/tree/master

extern crate libc;

#[macro_use]
mod macros;
pub mod ffi;

#[inline]
pub unsafe fn set_signal_handler(signal: ffi::c_int,
handler: unsafe extern "C" fn(ffi::c_int)) {
use libc::{sigaction, sighandler_t, sigfillset};
use std::{mem, ptr};

let mut sigset = mem::uninitialized();

// Block all signals during the handler. This is the expected behavior, but
// it's not guaranteed by `signal()`.
let rv = sigfillset(&mut sigset);
if rv == -1 {
return;
}

// Done because sigaction has private members.
// This is safe because sa_restorer and sa_handlers are pointers that
// might be null (that is, zero).
let mut action: sigaction = mem::zeroed();

// action.sa_flags = 0;
action.sa_mask = sigset;
action.sa_sigaction = handler as sighandler_t;

sigaction(signal, &action, ptr::null_mut());
}
18 changes: 7 additions & 11 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
#[macro_export]
macro_rules! getpid {
() => ({
extern crate sig;
unsafe { sig::ffi::getpid() }
unsafe { $crate::ffi::getpid() }
});
}

Expand All @@ -22,10 +21,9 @@ macro_rules! getpid {
#[macro_export]
macro_rules! signal {
($sig: expr, $fnc: expr) => ({
extern crate sig;
unsafe {
sig::ffi::signal (
$sig as i32,
$crate::set_signal_handler (
$sig as $crate::ffi::c_int,
$fnc
)
}
Expand All @@ -38,19 +36,17 @@ macro_rules! signal {
#[macro_export]
macro_rules! kill {
($pid: expr) => ({
extern crate sig;
kill!($pid, sig::ffi::Sig::KILL)
});
($pid: expr, $sig: expr) => ({
extern crate sig;
match unsafe {
sig::ffi::kill (
$pid as i32,
$sig as i32,
$pid as $crate::ffi::pid_t,
$sig as $crate::ffi::c_int,
)
} {
-1i32 => false,
_ => true,
-1 => true,
_ => false,
}
});
}