mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-30 00:00:16 +02:00
task: add test reproducing issue #1885
Signed-off-by: Eliza Weisman <[email protected]>
This commit is contained in:
+59
-1
@@ -506,6 +506,7 @@ impl Drop for Scheduler {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{runtime, task};
|
use crate::{runtime, task};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn local_current_thread() {
|
fn local_current_thread() {
|
||||||
@@ -729,7 +730,6 @@ mod tests {
|
|||||||
fn drop_cancels_tasks() {
|
fn drop_cancels_tasks() {
|
||||||
// This test reproduces issue #1842
|
// This test reproduces issue #1842
|
||||||
use crate::sync::oneshot;
|
use crate::sync::oneshot;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
let mut rt = runtime::Builder::new()
|
let mut rt = runtime::Builder::new()
|
||||||
.enable_time()
|
.enable_time()
|
||||||
@@ -753,4 +753,62 @@ mod tests {
|
|||||||
drop(local);
|
drop(local);
|
||||||
drop(rt);
|
drop(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn drop_cancels_remote_tasks() {
|
||||||
|
// This test reproduces issue #1885.
|
||||||
|
use std::sync::mpsc::RecvTimeoutError;
|
||||||
|
|
||||||
|
let (done_tx, done_rx) = std::sync::mpsc::channel();
|
||||||
|
let thread = std::thread::spawn(move || {
|
||||||
|
let (tx, mut rx) = crate::sync::mpsc::channel::<()>(1024);
|
||||||
|
|
||||||
|
let mut rt = runtime::Builder::new()
|
||||||
|
.enable_time()
|
||||||
|
.basic_scheduler()
|
||||||
|
.build()
|
||||||
|
.expect("building runtime should succeed");
|
||||||
|
|
||||||
|
let local = LocalSet::new();
|
||||||
|
local.spawn_local(async move { while let Some(_) = rx.recv().await {} });
|
||||||
|
local.block_on(&mut rt, async {
|
||||||
|
crate::time::delay_for(Duration::from_millis(1)).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
drop(tx);
|
||||||
|
|
||||||
|
// This enters an infinite loop if the remote notified tasks are not
|
||||||
|
// properly cancelled.
|
||||||
|
drop(local);
|
||||||
|
|
||||||
|
// Send a message on the channel so that the test thread can
|
||||||
|
// determine if we have entered an infinite loop:
|
||||||
|
done_tx.send(()).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Since the failure mode of this test is an infinite loop, rather than
|
||||||
|
// something we can easily make assertions about, we'll run it in a
|
||||||
|
// thread. When the test thread finishes, it will send a message on a
|
||||||
|
// channel to this thread. We'll wait for that message with a fairly
|
||||||
|
// generous timeout, and if we don't recieve it, we assume the test
|
||||||
|
// thread has hung.
|
||||||
|
//
|
||||||
|
// Note that it should definitely complete in under a minute, but just
|
||||||
|
// in case CI is slow, we'll give it a long timeout.
|
||||||
|
match done_rx.recv_timeout(Duration::from_secs(60)) {
|
||||||
|
Err(RecvTimeoutError::Timeout) => panic!(
|
||||||
|
"test did not complete within 60 seconds, \
|
||||||
|
we have (probably) entered an infinite loop!"
|
||||||
|
),
|
||||||
|
// Did the test thread panic? We'll find out for sure when we `join`
|
||||||
|
// with it.
|
||||||
|
Err(RecvTimeoutError::Disconnected) => {
|
||||||
|
println!("done_rx dropped, did the test thread panic?");
|
||||||
|
}
|
||||||
|
// Test completed successfully!
|
||||||
|
Ok(()) => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread.join().expect("test thread should not panic!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user