runtime: consolidate errors for context missing (#3441)

This commit is contained in:
Arve Knudsen 2021-01-20 14:29:13 +01:00 committed by GitHub
parent 36cf95ab62
commit fdde5583f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 77 additions and 24 deletions

View File

@ -259,8 +259,7 @@ cfg_rt! {
/// This function panics if there is no current reactor set and `rt` feature
/// flag is not enabled.
pub(super) fn current() -> Self {
crate::runtime::context::io_handle()
.expect("there is no reactor running, must be called from the context of Tokio runtime")
crate::runtime::context::io_handle().expect("A Tokio 1.x context was found, but IO is disabled. Call `enable_io` on the runtime builder to enable IO.")
}
}
}
@ -274,7 +273,7 @@ cfg_not_rt! {
/// This function panics if there is no current reactor set, or if the `rt`
/// feature flag is not enabled.
pub(super) fn current() -> Self {
panic!("there is no reactor running, must be called from the context of Tokio runtime with `rt` enabled.")
panic!(crate::util::error::CONTEXT_MISSING_ERROR)
}
}
}

View File

@ -9,6 +9,7 @@ use crate::runtime::builder::ThreadNameFn;
use crate::runtime::context;
use crate::runtime::task::{self, JoinHandle};
use crate::runtime::{Builder, Callback, Handle};
use crate::util::error::CONTEXT_MISSING_ERROR;
use std::collections::{HashMap, VecDeque};
use std::fmt;
@ -81,7 +82,7 @@ where
F: FnOnce() -> R + Send + 'static,
R: Send + 'static,
{
let rt = context::current().expect("not currently running on the Tokio runtime.");
let rt = context::current().expect(CONTEXT_MISSING_ERROR);
rt.spawn_blocking(func)
}
@ -91,7 +92,7 @@ where
F: FnOnce() -> R + Send + 'static,
R: Send + 'static,
{
let rt = context::current().expect("not currently running on the Tokio runtime.");
let rt = context::current().expect(CONTEXT_MISSING_ERROR);
let (task, _handle) = task::joinable(BlockingTask::new(func));
rt.blocking_spawner.spawn(task, &rt)

View File

@ -13,9 +13,9 @@ pub(crate) fn current() -> Option<Handle> {
cfg_io_driver! {
pub(crate) fn io_handle() -> crate::runtime::driver::IoHandle {
CONTEXT.with(|ctx| match *ctx.borrow() {
Some(ref ctx) => ctx.io_handle.clone(),
None => Default::default(),
CONTEXT.with(|ctx| {
let ctx = ctx.borrow();
ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).io_handle.clone()
})
}
}
@ -23,18 +23,18 @@ cfg_io_driver! {
cfg_signal_internal! {
#[cfg(unix)]
pub(crate) fn signal_handle() -> crate::runtime::driver::SignalHandle {
CONTEXT.with(|ctx| match *ctx.borrow() {
Some(ref ctx) => ctx.signal_handle.clone(),
None => Default::default(),
CONTEXT.with(|ctx| {
let ctx = ctx.borrow();
ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).signal_handle.clone()
})
}
}
cfg_time! {
pub(crate) fn time_handle() -> crate::runtime::driver::TimeHandle {
CONTEXT.with(|ctx| match *ctx.borrow() {
Some(ref ctx) => ctx.time_handle.clone(),
None => Default::default(),
CONTEXT.with(|ctx| {
let ctx = ctx.borrow();
ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).time_handle.clone()
})
}

View File

@ -1,6 +1,7 @@
use crate::runtime::blocking::task::BlockingTask;
use crate::runtime::task::{self, JoinHandle};
use crate::runtime::{blocking, context, driver, Spawner};
use crate::util::error::CONTEXT_MISSING_ERROR;
use std::future::Future;
use std::{error, fmt};
@ -97,7 +98,7 @@ impl Handle {
/// # }
/// ```
pub fn current() -> Self {
context::current().expect("not currently running on the Tokio runtime.")
context::current().expect(CONTEXT_MISSING_ERROR)
}
/// Returns a Handle view over the currently running Runtime
@ -213,7 +214,7 @@ impl fmt::Debug for TryCurrentError {
impl fmt::Display for TryCurrentError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("no tokio Runtime has been initialized")
f.write_str(CONTEXT_MISSING_ERROR)
}
}

View File

@ -1,5 +1,6 @@
use crate::runtime;
use crate::task::JoinHandle;
use crate::util::error::CONTEXT_MISSING_ERROR;
use std::future::Future;
@ -129,7 +130,7 @@ cfg_rt! {
T::Output: Send + 'static,
{
let spawn_handle = runtime::context::spawn_handle()
.expect("must be called from the context of Tokio runtime configured with either `basic_scheduler` or `threaded_scheduler`");
.expect(CONTEXT_MISSING_ERROR);
let task = crate::util::trace::task(task, "task");
spawn_handle.spawn(task)
}

View File

@ -47,7 +47,7 @@ cfg_rt! {
/// panicking.
pub(crate) fn current() -> Self {
crate::runtime::context::time_handle()
.expect("there is no timer running, must be called from the context of Tokio runtime")
.expect("A Tokio 1.x context was found, but timers are disabled. Call `enable_time` on the runtime builder to enable timers.")
}
}
}
@ -71,8 +71,7 @@ cfg_not_rt! {
/// lazy, and so outside executed inside the runtime successfuly without
/// panicking.
pub(crate) fn current() -> Self {
panic!("there is no timer running, must be called from the context of Tokio runtime or \
`rt` is not enabled")
panic!(crate::util::error::CONTEXT_MISSING_ERROR)
}
}
}

3
tokio/src/util/error.rs Normal file
View File

@ -0,0 +1,3 @@
/// Error string explaining that the Tokio context hasn't been instantiated.
pub(crate) const CONTEXT_MISSING_ERROR: &str =
"there is no reactor running, must be called from the context of a Tokio 1.x runtime";

View File

@ -35,3 +35,12 @@ pub(crate) mod trace;
#[cfg(any(feature = "macros"))]
#[cfg_attr(not(feature = "macros"), allow(unreachable_pub))]
pub use rand::thread_rng_n;
#[cfg(any(
feature = "rt",
feature = "time",
feature = "net",
feature = "process",
all(unix, feature = "signal")
))]
pub(crate) mod error;

View File

@ -84,3 +84,16 @@ fn test_drop_on_notify() {
// Force the reactor to turn
rt.block_on(async {});
}
#[test]
#[should_panic(
expected = "A Tokio 1.x context was found, but IO is disabled. Call `enable_io` on the runtime builder to enable IO."
)]
fn panics_when_io_disabled() {
let rt = runtime::Builder::new_current_thread().build().unwrap();
rt.block_on(async {
let _ =
tokio::net::TcpListener::from_std(std::net::TcpListener::bind("127.0.0.1:0").unwrap());
});
}

View File

@ -7,13 +7,17 @@ use futures::executor::block_on;
use std::net::TcpListener;
#[test]
#[should_panic(expected = "no timer running")]
fn panics_when_no_timer() {
#[should_panic(
expected = "there is no reactor running, must be called from the context of a Tokio 1.x runtime"
)]
fn timeout_panics_when_no_tokio_context() {
block_on(timeout_value());
}
#[test]
#[should_panic(expected = "no reactor running")]
#[should_panic(
expected = "there is no reactor running, must be called from the context of a Tokio 1.x runtime"
)]
fn panics_when_no_reactor() {
let srv = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = srv.local_addr().unwrap();
@ -25,3 +29,11 @@ async fn timeout_value() {
let dur = Duration::from_millis(20);
let _ = timeout(dur, rx).await;
}
#[test]
#[should_panic(
expected = "there is no reactor running, must be called from the context of a Tokio 1.x runtime"
)]
fn io_panics_when_no_tokio_context() {
let _ = tokio::net::TcpListener::from_std(std::net::TcpListener::bind("127.0.0.1:0").unwrap());
}

View File

@ -6,7 +6,7 @@ use tokio::sync::oneshot;
use tokio_test::{assert_err, assert_ok};
use std::thread;
use std::time::Duration;
use tokio::time::{timeout, Duration};
mod support {
pub(crate) mod mpsc_stream;
@ -135,6 +135,21 @@ fn acquire_mutex_in_drop() {
drop(rt);
}
#[test]
#[should_panic(
expected = "A Tokio 1.x context was found, but timers are disabled. Call `enable_time` on the runtime builder to enable timers."
)]
fn timeout_panics_when_no_time_handle() {
let rt = tokio::runtime::Builder::new_current_thread()
.build()
.unwrap();
rt.block_on(async {
let (_tx, rx) = oneshot::channel::<()>();
let dur = Duration::from_millis(20);
let _ = timeout(dur, rx).await;
});
}
fn rt() -> Runtime {
tokio::runtime::Builder::new_current_thread()
.enable_all()