Skip to content

Commit

Permalink
Merge #830
Browse files Browse the repository at this point in the history
830: Add alarm r=asomers a=Thomasdezeeuw

Fixed #828.
  • Loading branch information
bors[bot] committed Jan 8, 2018
2 parents abd72be + 0462201 commit f957cad
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#814](https://github.com/nix-rust/nix/pull/814))
- Added `sigprocmask` to the signal module.
([#826](https://github.com/nix-rust/nix/pull/826))
- Added `alarm`.
([#830](https://github.com/nix-rust/nix/pull/830))

### Changed
- Use native `pipe2` on all BSD targets. Users should notice no difference.
Expand Down
10 changes: 10 additions & 0 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,16 @@ pub fn pause() -> Result<()> {
Errno::result(res).map(drop)
}

/// Schedule or cancel an alarm signal.
///
/// If `secs` > 0 this will set an alarm, if its 0 this will cancel a previously
/// set alarm. Returns the time remaining on a previously set alarm, if any.
///
/// See also [alarm](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
pub fn alarm(secs: libc::c_uint) -> libc::c_uint {
unsafe { libc::alarm(secs) }
}

/// Suspend execution for an interval of time
///
/// See also [sleep(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
Expand Down
51 changes: 50 additions & 1 deletion test/test_unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ extern crate tempdir;
use nix::fcntl::{fcntl, FcntlArg, FdFlag, OFlag};
use nix::unistd::*;
use nix::unistd::ForkResult::*;
use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
use nix::sys::wait::*;
use nix::sys::stat::{self, Mode, SFlag};
use std::{self, env, iter};
Expand All @@ -12,7 +13,7 @@ use std::io::Write;
use std::os::unix::prelude::*;
use tempfile::tempfile;
use tempdir::TempDir;
use libc::{_exit, off_t};
use libc::{self, _exit, off_t};

#[test]
fn test_fork_and_waitpid() {
Expand Down Expand Up @@ -400,3 +401,51 @@ fn test_pipe2() {
let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap());
assert!(f1.contains(FdFlag::FD_CLOEXEC));
}

// Used in `test_alarm`.
static mut ALARM_CALLED: bool = false;

// Used in `test_alarm`.
pub extern fn alarm_signal_handler(raw_signal: libc::c_int) {
assert_eq!(raw_signal, libc::SIGALRM, "unexpected signal: {}", raw_signal);
unsafe { ALARM_CALLED = true };
}

#[test]
fn test_alarm() {
let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");

let handler = SigHandler::Handler(alarm_signal_handler);
let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty());
let old_handler = unsafe {
sigaction(Signal::SIGALRM, &signal_action)
.expect("unable to set signal handler for alarm")
};

// Set an alarm.
assert_eq!(alarm(60), 0);

// Overwriting an alarm should return the old alarm.
assert_eq!(alarm(1), 60);

// We should be woken up after 1 second by the alarm, so we'll sleep for 2
// seconds to be sure.
sleep(2);
assert_eq!(unsafe { ALARM_CALLED }, true, "expected our alarm signal handler to be called");

// Reset the signal.
unsafe {
sigaction(Signal::SIGALRM, &old_handler)
.expect("unable to set signal handler for alarm");
}
}

#[test]
fn test_canceling_alarm() {
let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");

assert_eq!(alarm(0), 0);

assert_eq!(alarm(60), 0);
assert_eq!(alarm(0), 60);
}

0 comments on commit f957cad

Please sign in to comment.