task: fix panic when dropping LocalSet (#1843)

It turns out that the `Scheduler::release` method on `LocalSet`'s
`Scheduler` *is* called, when the  `Scheduler` is dropped with tasks
still running. Currently, that method is `unreachable!`, which means
that dropping a `LocalSet` with tasks running will panic.

This commit fixes the panic, by pushing released tasks to
`pending_drop`. This is the same as `BasicScheduler`.

Fixes #1842
This commit is contained in:
Eliza Weisman
2019-11-27 14:24:44 -08:00
committed by Carl Lerche
parent 34d751bf92
commit 524e66314f
+31 -2
View File
@@ -345,8 +345,9 @@ impl Schedule for Scheduler {
}
}
fn release(&self, _: Task<Self>) {
unreachable!("tasks should only be completed locally")
fn release(&self, task: Task<Self>) {
// This will be called when dropping the local runtime.
self.pending_drop.push(task);
}
fn release_local(&self, task: &Task<Self>) {
@@ -724,4 +725,32 @@ mod tests {
join2.await.unwrap()
});
}
#[test]
fn drop_cancels_tasks() {
// This test reproduces issue #1842
use crate::sync::oneshot;
use std::time::Duration;
let mut rt = runtime::Builder::new()
.enable_time()
.basic_scheduler()
.build()
.unwrap();
let (started_tx, started_rx) = oneshot::channel();
let local = LocalSet::new();
local.spawn_local(async move {
started_tx.send(()).unwrap();
loop {
crate::time::delay_for(Duration::from_secs(3600)).await;
}
});
local.block_on(&mut rt, async {
started_rx.await.unwrap();
});
drop(local);
drop(rt);
}
}