Vendor dependencies
Let's see how I like this workflow.
This commit is contained in:
parent
34d1830413
commit
9c435dc440
7500 changed files with 1665121 additions and 99 deletions
81
vendor/signal-hook/tests/shutdown.rs
vendored
Normal file
81
vendor/signal-hook/tests/shutdown.rs
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
//! Tests for the shutdown.
|
||||
//!
|
||||
//! The tests work like this:
|
||||
//!
|
||||
//! * The register an alarm, to fail if anything takes too long (which is very much possible here).
|
||||
//! * A fork is done, with the child registering a signal with a NOP and cleanup operation (one or
|
||||
//! the other).
|
||||
//! * The child puts some kind of infinite loop or sleep inside itself, so it never actually
|
||||
//! terminates on the first, but would terminate after the signal.
|
||||
|
||||
#![cfg(not(windows))] // Forks don't work on Windows, but windows has the same implementation.
|
||||
|
||||
use std::io::Error;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use signal_hook::consts::signal::*;
|
||||
use signal_hook::flag;
|
||||
use signal_hook::low_level;
|
||||
|
||||
fn do_test<C: FnOnce()>(child: C) {
|
||||
unsafe {
|
||||
libc::alarm(10); // Time out the test after 10 seconds and get it killed.
|
||||
match libc::fork() {
|
||||
-1 => panic!("Fork failed: {}", Error::last_os_error()),
|
||||
0 => {
|
||||
child();
|
||||
loop {
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
pid => {
|
||||
// Give the child some time to register signals and stuff
|
||||
// We could actually signal that the child is ready by it eg. closing STDOUT, but
|
||||
// this is just a test so we don't really bother.
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
libc::kill(pid, libc::SIGTERM);
|
||||
// Wait a small bit to make sure the signal got delivered.
|
||||
thread::sleep(Duration::from_millis(50));
|
||||
// The child is still running, because the first signal got "handled" by being
|
||||
// ignored.
|
||||
let terminated = libc::waitpid(pid, ptr::null_mut(), libc::WNOHANG);
|
||||
assert_eq!(0, terminated, "Process {} terminated prematurely", pid);
|
||||
// But it terminates on the second attempt (we do block on wait here).
|
||||
libc::kill(pid, libc::SIGTERM);
|
||||
let terminated = libc::waitpid(pid, ptr::null_mut(), 0);
|
||||
assert_eq!(pid, terminated);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Use automatic cleanup inside the signal handler to get rid of old signals, the aggressive way.
|
||||
#[test]
|
||||
fn cleanup_inside_signal() {
|
||||
fn hook() {
|
||||
// Make sure we have some signal handler, not the default.
|
||||
unsafe { low_level::register(SIGTERM, || ()).unwrap() };
|
||||
let shutdown_cond = Arc::new(AtomicBool::new(false));
|
||||
// „disarmed“ shutdown
|
||||
flag::register_conditional_shutdown(SIGTERM, 0, Arc::clone(&shutdown_cond)).unwrap();
|
||||
// But arm at the first SIGTERM
|
||||
flag::register(SIGTERM, shutdown_cond).unwrap();
|
||||
}
|
||||
do_test(hook);
|
||||
}
|
||||
|
||||
/// Manually remove the signal handler just after receiving the signal but before going into an
|
||||
/// infinite loop.
|
||||
#[test]
|
||||
fn cleanup_after_signal() {
|
||||
fn hook() {
|
||||
let mut signals = signal_hook::iterator::Signals::new(&[libc::SIGTERM]).unwrap();
|
||||
assert_eq!(Some(SIGTERM), signals.into_iter().next());
|
||||
flag::register_conditional_shutdown(SIGTERM, 0, Arc::new(AtomicBool::new(true))).unwrap();
|
||||
}
|
||||
do_test(hook);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue