mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-28 00:00:11 +02:00
signal: move into tokio-net (#1463)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user