signal: move into tokio-net (#1463)

This commit is contained in:
Carl Lerche
2019-08-17 13:43:55 -07:00
committed by Ivan Petkov
parent a83f5e4ba6
commit c187cd75b6
28 changed files with 109 additions and 383 deletions
+36
View File
@@ -0,0 +1,36 @@
#![cfg(unix)]
#![cfg(feature = "signal")]
#![warn(rust_2018_idioms)]
pub mod signal_support;
use crate::signal_support::*;
#[test]
fn dropping_loops_does_not_cause_starvation() {
let (mut rt, signal) = {
let kind = SignalKind::user_defined1();
let mut first_rt = CurrentThreadRuntime::new().expect("failed to init first runtime");
let mut first_signal = Signal::new(kind).expect("failed to register first signal");
let mut second_rt = CurrentThreadRuntime::new().expect("failed to init second runtime");
let mut second_signal = Signal::new(kind).expect("failed to register second signal");
send_signal(libc::SIGUSR1);
let _ = run_with_timeout(&mut first_rt, first_signal.next())
.expect("failed to await first signal");
let _ = run_with_timeout(&mut second_rt, second_signal.next())
.expect("failed to await second signal");
drop(first_rt);
drop(first_signal);
(second_rt, second_signal)
};
send_signal(libc::SIGUSR1);
let _ = run_with_timeout(&mut rt, signal.into_future());
}
@@ -0,0 +1,19 @@
#![cfg(unix)]
#![cfg(feature = "signal")]
#![warn(rust_2018_idioms)]
#![feature(async_await)]
pub mod signal_support;
use crate::signal_support::*;
#[tokio::test]
async fn drop_then_get_a_signal() {
let kind = SignalKind::user_defined1();
let signal = Signal::new(kind).expect("failed to create first signal");
drop(signal);
send_signal(libc::SIGUSR1);
let signal = Signal::new(kind).expect("failed to create second signal");
let _ = with_timeout(signal.into_future()).await;
}
@@ -0,0 +1,26 @@
#![cfg(unix)]
#![cfg(feature = "signal")]
#![warn(rust_2018_idioms)]
#![feature(async_await)]
pub mod signal_support;
use crate::signal_support::*;
#[tokio::test]
async fn dropping_signal_does_not_deregister_any_other_instances() {
let kind = SignalKind::user_defined1();
// NB: Testing for issue alexcrichton/tokio-signal#38:
// signals should not starve based on ordering
let first_duplicate_signal =
Signal::new(kind).expect("failed to register first duplicate signal");
let signal = Signal::new(kind).expect("failed to register signal");
let second_duplicate_signal =
Signal::new(kind).expect("failed to register second duplicate signal");
drop(first_duplicate_signal);
drop(second_duplicate_signal);
send_signal(libc::SIGUSR1);
let _ = with_timeout(signal.into_future()).await;
}
+40
View File
@@ -0,0 +1,40 @@
#![cfg(unix)]
#![cfg(feature = "signal")]
#![warn(rust_2018_idioms)]
pub mod signal_support;
use crate::signal_support::*;
use std::sync::mpsc::channel;
use std::thread;
#[test]
fn multi_loop() {
// An "ordinary" (non-future) channel
let (sender, receiver) = channel();
// Run multiple times, to make sure there are no race conditions
for _ in 0..10 {
// Run multiple event loops, each one in its own thread
let threads: Vec<_> = (0..4)
.map(|_| {
let sender = sender.clone();
thread::spawn(move || {
let mut rt = CurrentThreadRuntime::new().unwrap();
let signal = Signal::new(SignalKind::hangup()).unwrap();
sender.send(()).unwrap();
let _ = run_with_timeout(&mut rt, signal.into_future());
})
})
.collect();
// Wait for them to declare they're ready
for &_ in threads.iter() {
receiver.recv().unwrap();
}
// Send a signal
send_signal(libc::SIGHUP);
// Make sure the threads terminated correctly
for t in threads {
t.join().unwrap();
}
}
}
+18
View File
@@ -0,0 +1,18 @@
#![cfg(unix)]
#![cfg(feature = "signal")]
#![warn(rust_2018_idioms)]
#![feature(async_await)]
pub mod signal_support;
use crate::signal_support::*;
#[tokio::test]
async fn notify_both() {
let kind = SignalKind::user_defined2();
let signal1 = Signal::new(kind).expect("failed to create signal1");
let signal2 = Signal::new(kind).expect("failed to create signal2");
send_signal(libc::SIGUSR2);
let _ = with_timeout(future::join(signal1.into_future(), signal2.into_future())).await;
}
+37
View File
@@ -0,0 +1,37 @@
#![cfg(unix)]
#![cfg(feature = "signal")]
#![warn(rust_2018_idioms)]
#![feature(async_await)]
pub mod signal_support;
use crate::signal_support::*;
#[tokio::test]
async fn simple() {
let signal = Signal::new(SignalKind::user_defined1()).expect("failed to create signal");
send_signal(libc::SIGUSR1);
let _ = with_timeout(signal.into_future()).await;
}
#[tokio::test]
#[cfg(unix)]
async fn ctrl_c() {
use tokio::sync::oneshot;
use tokio_net::signal::CtrlC;
let ctrl_c = CtrlC::new().expect("failed to init ctrl_c");
let (fire, wait) = oneshot::channel();
// NB: simulate a signal coming in by exercising our signal handler
// to avoid complications with sending SIGINT to the test process
tokio::spawn(async {
wait.await.expect("wait failed");
send_signal(libc::SIGINT);
});
let _ = fire.send(());
let _ = with_timeout(ctrl_c.into_future()).await;
}
+31
View File
@@ -0,0 +1,31 @@
#![cfg(unix)]
#![warn(rust_2018_idioms)]
pub use tokio::runtime::current_thread::{self, Runtime as CurrentThreadRuntime};
use tokio::timer::Timeout;
pub use tokio_net::signal::unix::{Signal, SignalKind};
pub use futures_util::future;
use futures_util::future::FutureExt;
pub use futures_util::stream::StreamExt;
use libc::{c_int, getpid, kill};
use std::future::Future;
use std::time::Duration;
pub fn with_timeout<F: Future>(future: F) -> impl Future<Output = F::Output> {
Timeout::new(future, Duration::from_secs(1)).map(Result::unwrap)
}
pub fn run_with_timeout<F>(rt: &mut CurrentThreadRuntime, future: F) -> F::Output
where
F: Future,
{
rt.block_on(with_timeout(future))
}
#[cfg(unix)]
pub fn send_signal(signal: c_int) {
unsafe {
assert_eq!(kill(getpid(), signal), 0);
}
}
+22
View File
@@ -0,0 +1,22 @@
#![cfg(unix)]
#![cfg(feature = "signal")]
#![warn(rust_2018_idioms)]
#![feature(async_await)]
pub mod signal_support;
use crate::signal_support::*;
#[tokio::test]
async fn twice() {
let kind = SignalKind::user_defined1();
let mut signal = Signal::new(kind).expect("failed to get signal");
for _ in 0..2 {
send_signal(libc::SIGUSR1);
let (item, sig) = with_timeout(signal.into_future()).await;
assert_eq!(item, Some(()));
signal = sig;
}
}