tokio_core::reactor::Core hangs on a threaded scheduler

Created on 11 May 2020  ยท  5Comments  ยท  Source: tokio-rs/tokio

Version

โ”œโ”€โ”€ tokio v0.2.20
โ”‚   โ””โ”€โ”€ tokio-macros v0.2.5
โ””โ”€โ”€ tokio-core v0.1.17
    โ”œโ”€โ”€ tokio v0.1.22
    โ”‚   โ”œโ”€โ”€ tokio-codec v0.1.2
    โ”‚   โ”‚   โ””โ”€โ”€ tokio-io v0.1.13
    โ”‚   โ”œโ”€โ”€ tokio-current-thread v0.1.7
    โ”‚   โ”‚   โ””โ”€โ”€ tokio-executor v0.1.10
    โ”‚   โ”œโ”€โ”€ tokio-executor v0.1.10 (*)
    โ”‚   โ”œโ”€โ”€ tokio-fs v0.1.7
    โ”‚   โ”‚   โ”œโ”€โ”€ tokio-io v0.1.13 (*)
    โ”‚   โ”‚   โ””โ”€โ”€ tokio-threadpool v0.1.18
    โ”‚   โ”‚       โ””โ”€โ”€ tokio-executor v0.1.10 (*)
    โ”‚   โ”œโ”€โ”€ tokio-io v0.1.13 (*)
    โ”‚   โ”œโ”€โ”€ tokio-reactor v0.1.12
    โ”‚   โ”‚   โ”œโ”€โ”€ tokio-executor v0.1.10 (*)
    โ”‚   โ”‚   โ”œโ”€โ”€ tokio-io v0.1.13 (*)
    โ”‚   โ”‚   โ””โ”€โ”€ tokio-sync v0.1.8
    โ”‚   โ”œโ”€โ”€ tokio-sync v0.1.8 (*)
    โ”‚   โ”œโ”€โ”€ tokio-tcp v0.1.4
    โ”‚   โ”‚   โ”œโ”€โ”€ tokio-io v0.1.13 (*)
    โ”‚   โ”‚   โ””โ”€โ”€ tokio-reactor v0.1.12 (*)
    โ”‚   โ”œโ”€โ”€ tokio-threadpool v0.1.18 (*)
    โ”‚   โ”œโ”€โ”€ tokio-timer v0.2.13
    โ”‚   โ”‚   โ””โ”€โ”€ tokio-executor v0.1.10 (*)
    โ”‚   โ”œโ”€โ”€ tokio-udp v0.1.6
    โ”‚   โ”‚   โ”œโ”€โ”€ tokio-codec v0.1.2 (*)
    โ”‚   โ”‚   โ”œโ”€โ”€ tokio-io v0.1.13 (*)
    โ”‚   โ”‚   โ””โ”€โ”€ tokio-reactor v0.1.12 (*)
    โ”‚   โ””โ”€โ”€ tokio-uds v0.2.6
    โ”‚       โ”œโ”€โ”€ tokio-codec v0.1.2 (*)
    โ”‚       โ”œโ”€โ”€ tokio-io v0.1.13 (*)
    โ”‚       โ””โ”€โ”€ tokio-reactor v0.1.12 (*)
    โ”œโ”€โ”€ tokio-executor v0.1.10 (*)
    โ”œโ”€โ”€ tokio-io v0.1.13 (*)
    โ”œโ”€โ”€ tokio-reactor v0.1.12 (*)
    โ””โ”€โ”€ tokio-timer v0.2.13 (*)

full version tree: https://pastebin.com/L2jPWrJf

Platform

Linux ... 4.16.18 ... Wed Jan 15 09:20:21 PST 2020 x86_64 x86_64 x86_64 GNU/Linux

Subcrates

tokio-core

Description

Converting a future 0.3 to a future 0.1 and then running it on tokio::reactor::Core inside a threaded scheduler causes the code to hang.

Simple repro (available on this repo):

use futures::future::{FutureExt, TryFutureExt};

async fn do_work() {
    let mut core = tokio_core::reactor::Core::new().unwrap();
    let future03 = async {
        tokio::time::delay_for(std::time::Duration::from_millis(100)).await;
    };
    let res = core.run(future03.unit_error().boxed_local().compat());
    assert!(res.is_ok());
    println!("We good");
}

#[tokio::main]
async fn main() {
    do_work().await;
}

#[tokio::test]
async fn test() {
    do_work().await;
}

cargo test hangs
cargo run works

A-tokio C-question I-hang M-runtime

All 5 comments

If you block all of the executor's threads, then any future that relies on the executor (e.g. Tokio's time driver) will deadlock. The #[tokio::test] macro fails because it uses only one thread by default, whereas #[tokio::main] worked because you ran it on a computer with more than one cpu core.

To be specific, the core.run call blocks the surrounding Tokio executor. This is expected behaviour.

Using #[tokio::test(core_threads=2)] does the trick indeed. Thanks for clarifying.

That said, you shouldn't be doing this in the first case. What do you need tokio-core for, and why can't you run it outside of Tokio's worker threads?

if you need to do this, run tokio_core in a spawn_blocking closure.

@Darksonn We have some legacy code using futures 0.1 and we eventually ended up on that situation by awaiting a future inside the core (on chain of calls). It's a bug on our code, but it wasn't clear to me at the time.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JohnDoneth picture JohnDoneth  ยท  5Comments

polomsky picture polomsky  ยท  4Comments

ancwrd1 picture ancwrd1  ยท  5Comments

hawkw picture hawkw  ยท  5Comments

djc picture djc  ยท  4Comments