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

Panic 'no Task is currently running' in compat03as01 AsyncRead #1463

Closed
zargony opened this issue Feb 25, 2019 · 4 comments
Closed

Panic 'no Task is currently running' in compat03as01 AsyncRead #1463

zargony opened this issue Feb 25, 2019 · 4 comments

Comments

@zargony
Copy link
Contributor

zargony commented Feb 25, 2019

Wrapping a 0.3 AsyncRead+AsyncWrite object using compat03as01 to make it 0.1 AsyncRead+AsyncWrite compatible seems to panic with "no Task is currently running" every time it's being read from or written to.

I was actually trying to use a romio::TcpListener to accept connections and do a websocket handshake using tokio_tungstenite::accept_async, but here's a smaller example of the same problem:

#![feature(async_await, await_macro, futures_api)]

use std::error::Error;
use futures::prelude::*;
use futures::executor::block_on;
use tokio::io::AsyncRead;
use romio::TcpListener;

fn main() -> Result<(), Box<Error>> {
    block_on(async {
        let mut listener = TcpListener::bind(&"127.0.0.1:8080".parse()?)?;
        let mut incoming = listener.incoming();
        if let Some(stream) = await!(incoming.next()) {
            let stream = stream?;
            eprintln!("Incoming connection from {:?}", stream.peer_addr()?);
            let mut stream01 = stream.compat();
            let mut buffer = Vec::new();
            let res = stream01.read_buf(&mut buffer)?;      // panics: 'no Task is currently running'
            eprintln!("Result: {:?}", res);
        }
        Ok(())
    })
}

Versions:

  • futures-preview 0.3.0-alpha.13
  • romio 0.3.0-alpha.2 (git:4c0e6e2)
  • tokio 0.1.15 (for tokio::io only, no runtime)

Backtrace snippet:

  10: futures::task_impl::core::is_get_ptr
             at /Users/zargony/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.25/src/task_impl/mod.rs:43
  11: futures::task_impl::core::is_get_ptr
             at /Users/zargony/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-0.1.25/src/task_impl/mod.rs:115
  12: core::alloc::Layout::align
             at /Users/zargony/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.13/src/compat/compat03as01.rs:126
  13: futures_util::compat::compat03as01::io::<impl std::io::Read for futures_util::compat::compat03as01::Compat<R>>::read
             at /Users/zargony/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-preview-0.3.0-alpha.13/src/compat/compat03as01.rs:192
  14: tokio_io::async_read::AsyncRead::poll_read
             at /Users/zargony/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-io-0.1.11/src/async_read.rs:81
  15: tokio_io::async_read::AsyncRead::read_buf
             at /Users/zargony/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-io-0.1.11/src/async_read.rs:109
  16: async_io_compat_issue::main::{{closure}}
             at src/main.rs:18

Looks like Compat uses Current::new which in turn calls task01::current() which panics because there's no current task. This problem looks similar to #1251.

I couldn't get it to work (running in either LocalPool, ThreadPool or with executor::block_on, it always panics). I would expect that a current Task is provided automatically by the compat wrapper. Is this a bug or is there something special that needs to be done to provide a current task?

@tinaun
Copy link
Contributor

tinaun commented Feb 26, 2019

im pretty sure compat03as01 futures need to run inside a futures 0.1 executor to actually work

@LucioFranco
Copy link
Member

correct, currently the approach is to convert 0.1 futures into 0.3, write your code in 0.3 then convert the application future back into 0.1 to then pass it to a 0.1 executor.

@zargony
Copy link
Contributor Author

zargony commented Feb 27, 2019

I see. Thanks for the clarification. It actually works fine for me to run the 0.3 application future in a LocalPool or ThreadPool (mostly hyper clients and servers). It's just the websocket handshake I'm having troubles with.

It probably makes sense that the above example panics since it's calling read_buf (and therefore poll_read) without being inside a 0.1 task.
I think I minimized the example too much so that it isn't meaningful anymore. What I was actually trying to do: wrap a 0.3 TcpStream to make it 0.1 compatible, pass it to a handshake function to get a 0.1 future which is then wrapped to make it 0.3 compatible again and run it in a LocalPool or ThreadPool.

After trying harder, I found out that this generally seems to work. Compat01As03 seems to provide a current 0.1 task to the underlying future, which makes sense.

let fut01 = tokio::io::read(stream01, &mut buffer);          // do something on a 0.1 async io, returns 0.1 future
let (_, buffer, res) = await!( Compat01As03::new(fut01) )?;  // wrap to make it a 0.3 future and run it. works fine

The weird thing is, that the same approach doesn't work with the websocket handshake:

let ws_fut01 = tokio_tungstenite::accept_async(stream01);    // creates a 0.1 future that does a websocket handshake on the given 0.1 async io
let ws = await!( Compat01As03::new(ws_fut01) )?;             // panics with 'no Task is currently running' even though Compat01As03 should provide a current task?

However, this now looks more like a problem with tokio-tungstenite. Or is there anything in particular that a 0.1 future or async io implementation could do wrong in a way that lets it work fine in a real executor but panic if wrapped in Compat01As03?

@zargony
Copy link
Contributor Author

zargony commented Feb 27, 2019

I found out that I was mistaken by assuming that tokio_tungstenite::accept_async just creates a future. Instead, it seems to start the handshake and return a future to complete it. I.e. accept_async tries to read the stream immediately and not only when polling. In a pure 0.1 application one doesn't notice since it's called when getting the accepted TcpStream, which always happens in a task. Pretty tricky to debug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants