mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-29 00:00:11 +02:00
rt: avoid dropping a task in calls to wake() (#1972)
Calls to tasks should not be nested. Currently, while a task is being executed and the runtime is shutting down, a call to wake() can result in the wake target to be dropped. This, in turn, results in the drop handler being called. If the user holds a ref cell borrow, a mutex guard, or any such value, dropping the task inline can result in a deadlock. The fix is to permit tasks to be scheduled during the shutdown process and dropping the tasks once they are popped from the queue. Fixes #1929, #1886
This commit is contained in:
@@ -27,6 +27,42 @@ fn spawned_task_does_not_progress_without_block_on() {
|
||||
assert_eq!(out, "hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acquire_mutex_in_drop() {
|
||||
use futures::future::pending;
|
||||
use tokio::task;
|
||||
|
||||
let (tx1, rx1) = oneshot::channel();
|
||||
let (tx2, rx2) = oneshot::channel();
|
||||
|
||||
let mut rt = rt();
|
||||
|
||||
rt.spawn(async move {
|
||||
let _ = rx2.await;
|
||||
unreachable!();
|
||||
});
|
||||
|
||||
rt.spawn(async move {
|
||||
let _ = rx1.await;
|
||||
let _ = tx2.send(()).unwrap();
|
||||
unreachable!();
|
||||
});
|
||||
|
||||
// Spawn a task that will never notify
|
||||
rt.spawn(async move {
|
||||
pending::<()>().await;
|
||||
tx1.send(()).unwrap();
|
||||
});
|
||||
|
||||
// Tick the loop
|
||||
rt.block_on(async {
|
||||
task::yield_now().await;
|
||||
});
|
||||
|
||||
// Drop the rt
|
||||
drop(rt);
|
||||
}
|
||||
|
||||
fn rt() -> Runtime {
|
||||
tokio::runtime::Builder::new()
|
||||
.basic_scheduler()
|
||||
|
||||
Reference in New Issue
Block a user