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

"Cannot start a runtime from within a runtime." false positive? #2529

Closed
kornelski opened this issue May 12, 2020 · 8 comments
Closed

"Cannot start a runtime from within a runtime." false positive? #2529

kornelski opened this issue May 12, 2020 · 8 comments
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. I-crash Problems and improvements related to program crashes/panics. M-runtime Module: tokio/runtime

Comments

@kornelski
Copy link
Contributor

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?

@Darksonn Darksonn added A-tokio Area: The main tokio crate C-bug Category: This is a bug. I-crash Problems and improvements related to program crashes/panics. M-runtime Module: tokio/runtime labels May 12, 2020
@Darksonn
Copy link
Contributor

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();
}

@cssivision
Copy link
Contributor

cssivision commented May 15, 2020

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.

@Darksonn
Copy link
Contributor

@cssivision Oops, that's what I meant!

@jebrosen
Copy link
Contributor

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

@kornelski
Copy link
Contributor Author

@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.

@Darksonn
Copy link
Contributor

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

@neel0309
Copy link

is this issue resolved ?

@Darksonn
Copy link
Contributor

Yes, the panic message was fixed in #2646.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug. I-crash Problems and improvements related to program crashes/panics. M-runtime Module: tokio/runtime
Projects
None yet
Development

No branches or pull requests

5 participants