Tokio: "Cannot start a runtime from within a runtime." false positive?

Created on 12 May 2020  路  8Comments  路  Source: tokio-rs/tokio

I'm trying to create a second threaded runtime to act as a replacement of futures-cpupool (because reasons).

This code:

fn main() {
    let mut main_runtime = tokio::runtime::Runtime::new().unwrap();
    let cpu_pool = tokio::runtime::Builder::new().threaded_scheduler().build().unwrap();
    // let cpu_pool = cpu_pool.handle().clone();

    main_runtime.block_on(main_runtime.spawn(async move {
        cpu_pool.spawn(async {}).await
    }))
    .unwrap().unwrap();
}

Fails with:

thread 'tokio-runtime-worker' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like block_on) attempted to block the current thread while the thread is being used to drive asynchronous tasks.'

I don't think I'm violating any rules here: both runtimes are created outside of a runtime, and only one of them runs block_on.

On top of that, using Handle for spawn instead of the runtime directly, makes it work:

fn main() {
    let mut main_runtime = tokio::runtime::Runtime::new().unwrap();
    let cpu_pool = tokio::runtime::Builder::new().threaded_scheduler().build().unwrap();
    let cpu_pool = cpu_pool.handle().clone();

    main_runtime.block_on(main_runtime.spawn(async move {
        cpu_pool.spawn(async {}).await
    }))
    .unwrap().unwrap();
}

Is this the expected behavior?

A-tokio C-bug I-crash M-runtime

Most helpful comment

rt.block_on(async move {
    matching_rt.spawn(async {}).await
}).unwrap();

The problem here is async move: matching_rt is moved into the blocking task, and is dropped at the end. When matching_rt is dropped, it blocks to shut down all pending tasks.

Changing async move to async is enough to fix this example.

Relevant parts of the stack trace:

  11: std::panicking::begin_panic
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/panicking.rs:397
  12: tokio::runtime::enter::enter
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/enter.rs:38
  13: tokio::runtime::blocking::shutdown::Receiver::wait
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/blocking/shutdown.rs:44
  14: tokio::runtime::blocking::pool::BlockingPool::shutdown
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/blocking/pool.rs:132
  15: <tokio::runtime::blocking::pool::BlockingPool as core::ops::drop::Drop>::drop
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/blocking/pool.rs:138
  16: core::ptr::drop_in_place
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libcore/ptr/mod.rs:177
  17: core::ptr::drop_in_place
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libcore/ptr/mod.rs:177
  18: playground::main::{{closure}}
             at src/main.rs:11
  19: <std::future::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/future.rs:44
  20: tokio::runtime::enter::Enter::block_on::{{closure}}
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/enter.rs:163
  21: tokio::coop::budget::{{closure}}
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/coop.rs:97
  22: std::thread::local::LocalKey<T>::try_with
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/thread/local.rs:262
  23: std::thread::local::LocalKey<T>::with
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/thread/local.rs:239
  24: tokio::coop::budget
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/coop.rs:79
  25: tokio::runtime::enter::Enter::block_on
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/enter.rs:163
  26: tokio::runtime::thread_pool::ThreadPool::block_on
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/thread_pool/mod.rs:82
  27: tokio::runtime::Runtime::block_on::{{closure}}
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/mod.rs:446
  28: tokio::runtime::context::enter
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/context.rs:72
  29: tokio::runtime::handle::Handle::enter
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/handle.rs:71
  30: tokio::runtime::Runtime::block_on
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/mod.rs:441
  31: playground::main
             at src/main.rs:9

All 8 comments

Thank you for the bug report. This definitely seems like a bug. Note that this simplified version also panics:

use tokio::runtime::Builder;

fn main() {
    let mut rt = Builder::new().threaded_scheduler().build().unwrap();
    let matching_rt = Builder::new().threaded_scheduler().build().unwrap();

    let handle = matching_rt.handle().clone();

    rt.block_on(async move {
        handle.spawn(async {}).await
    }).unwrap();
}

Thank you for the bug report. This definitely seems like a bug. Note that this simplified version also panics:

use tokio::runtime::Builder;

fn main() {
    let mut rt = Builder::new().threaded_scheduler().build().unwrap();
    let matching_rt = Builder::new().threaded_scheduler().build().unwrap();

    let handle = matching_rt.handle().clone();

    rt.block_on(async move {
        handle.spawn(async {}).await
    }).unwrap();
}

this example do not panic, but if you replace handle.spawn with matching_rt.spawn it will panic.

@cssivision Oops, that's what I meant!

rt.block_on(async move {
    matching_rt.spawn(async {}).await
}).unwrap();

The problem here is async move: matching_rt is moved into the blocking task, and is dropped at the end. When matching_rt is dropped, it blocks to shut down all pending tasks.

Changing async move to async is enough to fix this example.

Relevant parts of the stack trace:

  11: std::panicking::begin_panic
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/panicking.rs:397
  12: tokio::runtime::enter::enter
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/enter.rs:38
  13: tokio::runtime::blocking::shutdown::Receiver::wait
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/blocking/shutdown.rs:44
  14: tokio::runtime::blocking::pool::BlockingPool::shutdown
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/blocking/pool.rs:132
  15: <tokio::runtime::blocking::pool::BlockingPool as core::ops::drop::Drop>::drop
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/blocking/pool.rs:138
  16: core::ptr::drop_in_place
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libcore/ptr/mod.rs:177
  17: core::ptr::drop_in_place
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libcore/ptr/mod.rs:177
  18: playground::main::{{closure}}
             at src/main.rs:11
  19: <std::future::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/future.rs:44
  20: tokio::runtime::enter::Enter::block_on::{{closure}}
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/enter.rs:163
  21: tokio::coop::budget::{{closure}}
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/coop.rs:97
  22: std::thread::local::LocalKey<T>::try_with
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/thread/local.rs:262
  23: std::thread::local::LocalKey<T>::with
             at /rustc/8d69840ab92ea7f4d323420088dd8c9775f180cd/src/libstd/thread/local.rs:239
  24: tokio::coop::budget
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/coop.rs:79
  25: tokio::runtime::enter::Enter::block_on
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/enter.rs:163
  26: tokio::runtime::thread_pool::ThreadPool::block_on
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/thread_pool/mod.rs:82
  27: tokio::runtime::Runtime::block_on::{{closure}}
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/mod.rs:446
  28: tokio::runtime::context::enter
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/context.rs:72
  29: tokio::runtime::handle::Handle::enter
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/handle.rs:71
  30: tokio::runtime::Runtime::block_on
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.20/src/runtime/mod.rs:441
  31: playground::main
             at src/main.rs:9

@jebrosen Thanks for the diagnosis.

Would it be possible to improve this error message to specifically mention it's coming from Tokio's own destructor? Destructors are invisible and I wouldn't have guessed it's about that, and not my spawn call.

I suppose that would be possible to do. These panic messages need improvement in any case, but this sounds like a reasonable idea.

is this issue resolved ?

Yes, the panic message was fixed in #2646.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

izolyomi picture izolyomi  路  5Comments

carllerche picture carllerche  路  4Comments

jonhoo picture jonhoo  路  3Comments

hawkw picture hawkw  路  5Comments

JohnDoneth picture JohnDoneth  路  5Comments