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

The first terminal event is ignored after using stdin #5535

Closed
dalance opened this issue Mar 9, 2023 · 2 comments
Closed

The first terminal event is ignored after using stdin #5535

dalance opened this issue Mar 9, 2023 · 2 comments
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug.

Comments

@dalance
Copy link

dalance commented Mar 9, 2023

Version

tokio v1.26.0

Platform

x86_64 GNU/Linux

Description

I want to use tokio::io::stdin with timeout and terminal event after it.
But the first event seems to be ignored.
The procedure of reproduce is below:

use crossterm::event::read;
use crossterm::terminal;
use std::time::Duration;

fn main() {
    let runtime = tokio::runtime::Builder::new_current_thread()
        .enable_time()
        .build()
        .unwrap();
    let buf = runtime.block_on(async {
        tokio::time::timeout(Duration::new(1, 0), async {
            use tokio::io::AsyncReadExt;
            let mut buf = [0; 1];
            let mut stdin = tokio::io::stdin();
            let _ = stdin.read_exact(&mut buf).await;
            buf
        })
        .await
    });
    dbg!(buf);

    terminal::enable_raw_mode().unwrap();

    println!("{:?}", read());

    terminal::disable_raw_mode().unwrap();
}
  • run the above code
  • wait until dbg! message is shown
  • press any key

I expected to see this happen: the first key pressing is shown

Instead, this happened: the first key pressing is ignored, and the second key pressing is shown.

If let buf = ... code block is commented out, the first key pressing is shown.

This seems to be the same behaviour as async_std.
async-rs/async-std#1055

Is there any usage mistake or any known limitation?

@Darksonn
Copy link
Contributor

Darksonn commented Mar 9, 2023

Reading from stdin is based on spawn_blocking, so you cannot cancel it, even with a timeout. It will keep running in the background.

This is a well known issue, and it is the reason we added this to the documentation for tokio::io::stdin.

This handle is best used for non-interactive uses, such as when a file is piped into the application. For technical reasons, stdin is implemented by using an ordinary blocking read on a separate thread, and it is impossible to cancel that read. This can make shutdown of the runtime hang until the user presses enter.

For interactive uses, it is recommended to spawn a thread dedicated to user input and use blocking IO directly in that thread.

Since your IO is interactive, I recommend not using Tokio's stdin for it.

@dalance
Copy link
Author

dalance commented Mar 9, 2023

I understood it. Thanks.

@dalance dalance closed this as completed Mar 9, 2023
eatradish added a commit to AOSC-Dev/oma that referenced this issue Sep 24, 2024
`async-std` and `tokio` stdin use `spawn_blocking` to handle stdin,
That is, `stdin` task does not end after the timeout, so no input
can be processed after opening the TUI.

This fix came from upstream: https://github.com/dalance/termbg/tree/non_blocking_stdin,
but it was not adopted by upstream because it doesn't compile under Windows, but fortunately
oma has no plans to support Windows for the time being.

ref:

- tokio-rs/tokio#5535
- async-rs/async-std#1055
- zellij-org/zellij#538
- https://github.com/zellij-org/zellij/blob/3569daf7c9cacc1dbbec6a3813079130b4c0683c/zellij-client/src/os_input_output.rs#L270
eatradish added a commit to AOSC-Dev/oma that referenced this issue Sep 24, 2024
`async-std` and `tokio` stdin use `spawn_blocking` to handle stdin,
That is, `stdin` task does not end after the timeout, so no input
can be processed after opening the TUI.

This fix came from upstream: https://github.com/dalance/termbg/tree/non_blocking_stdin,
but it was not adopted by upstream because it doesn't compile under Windows, but fortunately
oma has no plans to support Windows for the time being.

ref:

- tokio-rs/tokio#5535
- async-rs/async-std#1055
- zellij-org/zellij#538
- https://github.com/zellij-org/zellij/blob/3569daf7c9cacc1dbbec6a3813079130b4c0683c/zellij-client/src/os_input_output.rs#L270
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.
Projects
None yet
Development

No branches or pull requests

2 participants