Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow block_on inside block_in_place inside block_on #2645

Merged
merged 1 commit into from
Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion tokio/src/runtime/thread_pool/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,16 +200,19 @@ cfg_blocking! {
}

let mut had_core = false;
let mut had_entered = false;

CURRENT.with(|maybe_cx| {
match (crate::runtime::enter::context(), maybe_cx.is_some()) {
(EnterContext::Entered { .. }, true) => {
// We are on a thread pool runtime thread, so we just need to set up blocking.
had_entered = true;
}
(EnterContext::Entered { allow_blocking }, false) => {
// We are on an executor, but _not_ on the thread pool.
// That is _only_ okay if we are in a thread pool runtime's block_on method:
if allow_blocking {
had_entered = true;
return;
} else {
// This probably means we are on the basic_scheduler or in a LocalSet,
Expand Down Expand Up @@ -256,12 +259,13 @@ cfg_blocking! {
runtime::spawn_blocking(move || run(worker));
});


if had_core {
// Unset the current task's budget. Blocking sections are not
// constrained by task budgets.
let _reset = Reset(coop::stop());

crate::runtime::enter::exit(f)
} else if had_entered {
crate::runtime::enter::exit(f)
} else {
f()
Expand Down
19 changes: 19 additions & 0 deletions tokio/tests/task_blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,22 @@ fn no_block_in_basic_block_on() {
task::block_in_place(|| {});
});
}

#[test]
fn can_enter_basic_rt_from_within_block_in_place() {
let mut outer = tokio::runtime::Builder::new()
.threaded_scheduler()
.build()
.unwrap();

outer.block_on(async {
tokio::task::block_in_place(|| {
let mut inner = tokio::runtime::Builder::new()
.basic_scheduler()
.build()
.unwrap();

inner.block_on(async {})
})
});
}