provide a way to drop a runtime in an async context (#2646)

Dropping a runtime normally involves waiting for any outstanding blocking tasks
to complete. When this drop happens in an asynchronous context, we previously
would issue a cryptic panic due to trying to block in an asynchronous context.

This change improves the panic message, and adds a `shutdown_blocking()` function
which can be used to shutdown a runtime without blocking at all, as an out for
cases where this really is necessary.

Co-authored-by: Bryan Donlan <[email protected]>
Co-authored-by: Alice Ryhl <[email protected]>
This commit is contained in:
bdonlan
2020-07-21 15:26:47 -07:00
committed by GitHub
co-authored by Bryan Donlan Alice Ryhl
parent 28a93e6044
commit 04a2826084
3 changed files with 108 additions and 7 deletions
+61
View File
@@ -115,3 +115,64 @@ fn can_enter_basic_rt_from_within_block_in_place() {
})
});
}
#[test]
fn useful_panic_message_when_dropping_rt_in_rt() {
use std::panic::{catch_unwind, AssertUnwindSafe};
let mut outer = tokio::runtime::Builder::new()
.threaded_scheduler()
.build()
.unwrap();
let result = catch_unwind(AssertUnwindSafe(|| {
outer.block_on(async {
let _ = tokio::runtime::Builder::new()
.basic_scheduler()
.build()
.unwrap();
});
}));
assert!(result.is_err());
let err = result.unwrap_err();
let err: &'static str = err.downcast_ref::<&'static str>().unwrap();
assert!(
err.find("Cannot drop a runtime").is_some(),
"Wrong panic message: {:?}",
err
);
}
#[test]
fn can_shutdown_with_zero_timeout_in_runtime() {
let mut outer = tokio::runtime::Builder::new()
.threaded_scheduler()
.build()
.unwrap();
outer.block_on(async {
let rt = tokio::runtime::Builder::new()
.basic_scheduler()
.build()
.unwrap();
rt.shutdown_timeout(Duration::from_nanos(0));
});
}
#[test]
fn can_shutdown_now_in_runtime() {
let mut outer = tokio::runtime::Builder::new()
.threaded_scheduler()
.build()
.unwrap();
outer.block_on(async {
let rt = tokio::runtime::Builder::new()
.basic_scheduler()
.build()
.unwrap();
rt.shutdown_background();
});
}