Skip to content

Commit

Permalink
task: fix panic when dropping LocalSet (#1843)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
hawkw authored and carllerche committed Nov 27, 2019
1 parent 34d751b commit 524e663
Showing 1 changed file with 31 additions and 2 deletions.
33 changes: 31 additions & 2 deletions tokio/src/task/local.rs
Expand Up @@ -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>) {
Expand Down Expand Up @@ -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);
}
}

0 comments on commit 524e663

Please sign in to comment.