Repository: actix/actix (language: rust)

Issue:
Actix does not read from tokio::io::stdin()
I created an actor that implements StreamHandler and it's expected to receive messages from tokio::io::stdin(); however, it seems that there's no way to get the messages as expected.
Here the code of the actor:
```
pub fn start_actix_stdin() {
    System::run(move || {
        StdinActor::create(move |ctx| {
            let codec = LinesCodec::new();
            let source = tokio::io::stdin();
            let framed = FramedRead::new(source, codec).map(LineMessage);
            StdinActor::add_stream(framed, ctx);
            StdinActor {}
        });
    });
}

#[derive(Message)]
pub struct LineMessage(pub String);

pub struct StdinActor {}

impl Actor for StdinActor {
    type Context = Context<Self>;
    fn started(&mut self, _ctx: &mut Self::Context) { println!("StdinActor started."); }
}

impl StreamHandler<LineMessage, std::io::Error> for StdinActor {
    fn handle(&mut self, msg: LineMessage, _ctx: &mut Self::Context) {
        println!("StdinActor - Received msg: [{}]", &msg.0);
    }
}
```

The actor starts as expected but no input is received.
Here a complete reproducer: https://github.com/ufoscout/actix_stdio

You can check the behavior this way:

1. clone and build
2. launch it with a pipe in a unix-like shell, e.g.:
```ls -latr | ./target/debug/actix_stdio```

I expected the 'ls' output to be piped into my application and then to be printed; anyway, the actor receives no messages.

Notes:
- The repository with the reproducer contains also an implementation based on std::io that works as expected
- I tested it only on a Ubuntu 18.04 64bit OS



Discussion / hints:
Internally all ops on `Stdin` are blocking so you actually block yourself when reading it I think?
Since actix uses single threaded event loop there is not way to make it work afaik

https://github.com/tokio-rs/tokio/blob/f929576f0ea0debedd31cccd9b5a336ea1687568/tokio-fs/src/lib.rs#L87-L99

The function that is used internally by tokio and requires threaded runtime since blocking off loads work to another thread as far as I know.

I'd suggest to check on tokio gitter to be sure though
Hi @DoumanAsh, thanks for your reply.

From the docs of the code you linked:
> This module offers adapters which use a [`blocking`] annotation
//! to inform the runtime that a blocking operation is required. When
//! necessary, this allows the runtime to convert the current thread from a
//! *worker* to a *backup* thread, where blocking is acceptable.
...
//! Where possible, users should prefer the provided asynchronous-specific
//! traits such as [`AsyncRead`], or methods returning a `Future` or `Poll`
//! type. Adaptions also extend to traits like `std::io::Read` where methods
//! return `std::io::Result`.  Be warned that these adapted methods may return
//! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted
//! to a *backup* thread immediately.

It is not completely clear to me, anyway, it seems to refer to the fact that the tokio runtime should not block due to the 'blocking' annotation. Also, in my code I am using the stdin as an 'AsyncRead', so based on the docs, it should be automatically moved to a backup thread or immediately return a `std::io::ErrorKind::WouldBlock` error. 
Am I wrong?

It is still not clear to me whether this has to be investigated in actix or tokio tough.
`blocking` annotation is only available with threading exectuor, as far as I know it is not possible to use in from `current_thread` runtime(which is used by actix)

Though if it blocks forever, it is most likely unexpected problem in tokio, because if I understand tokio model correctly in case of `current_thread` it should always return `std::io::ErrorKind::WouldBlock` which would render it unusable

`warp` for example mentions this about its usage of `tokio-fs`
https://docs.rs/warp/0.1.9/warp/filters/fs/fn.dir.html

>This filter uses tokio-fs to serve files, which requires the server to be run in the threadpool runtime. This is only important to remember if starting a runtime manually.

For clarification:

>It is not completely clear to me, anyway, it seems to refer to the fact that the tokio runtime should not block due to the 'blocking' annotation

To clarify, `blocking` calls are just off loading to thread worker in order to not block event loop, but with `current_thread` runtime there is only single thread to do job
I'm not sure what's behavior of `blocking` with `current_thread` runtime though
I reported the issue directly to the tokio team (see https://github.com/tokio-rs/tokio/issues/788 )

I also noticed that they have already planned to uniform the behaviour of tokio::fs across all runtimes (see
https://github.com/tokio-rs/tokio/issues/629 ). So, one day, this should hopefully be resolved by a simple dependency upgrade.

At this point, it is clear that the issue is not in actix. However, actix is affected by this weird behaviour at the moment. 
Could this maybe be documented? I spent lots of hours due to this; it could save other people from the same painful investigation.
Well yeah, I guess it could be useful to note it in docs
@DoumanAsh 
one question, should I expect the same issue when reading/writing a file on the file system?
if you mean by using `tokio-fs` then yes, you cannot use it with current thread runtime
I just checked your example, and tokio does return error in this case, but you do not see it as you haven't implemented error handler for your stream:

```rust
/// To use `Framed` with an actor, we have to implement `StreamHandler` trait
impl StreamHandler<LineMessage, std::io::Error> for StdinActor {
    fn error(&mut self, err: std::io::Error, ctx: &mut Self::Context) -> actix::Running {
        println!("ERROR: {}", err);
        actix::Running::Stop
    }

    fn handle(&mut self, msg: LineMessage, _ctx: &mut Self::Context) {
        println!("StdinActor - Received msg: [{}]", &msg.0);
    }
}
```

If you impl, you'd see error immediately.

In anyway ways I do not mind to have it in docs, but it is difficult to find appropriate place.
In first place, actix assumes that you're familiar with tokio, so there is no documentation on tokio and its quirks overall

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index 00c11ff71..b352cf1f7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -29,6 +29,17 @@
 //! * `resolver` - enables dns resolver actor, `actix::actors::resolver`
 //! * `signal` - enables signals handling actor
 //!
+//! ## Tokio runtime
+//!
+//! At the moment actix uses
+//! [`current_thread`](https://docs.rs/tokio/0.1.13/tokio/runtime/current_thread/index.html) runtime.
+//!
+//! While it provides minimum overhead, it has its own limits:
+//!
+//! - You cannot use tokio's async file I/O, as it relies on blocking calls that are not available
+//! in `current_thread`
+//! - `Stdin`, `Stderr` and `Stdout` from `tokio::io` are the same as file I/O in that regard and
+//! cannot be used in asynchronous manner in actix.
 #[macro_use]
 extern crate log;
 extern crate bytes;


Test patch: