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

EventStream spawns a new thread on every event #448

Closed
mcobzarenco opened this issue Jun 29, 2020 · 1 comment · Fixed by #503
Closed

EventStream spawns a new thread on every event #448

mcobzarenco opened this issue Jun 29, 2020 · 1 comment · Fixed by #503

Comments

@mcobzarenco
Copy link

mcobzarenco commented Jun 29, 2020

Describe the bug
Using EventStream seems to spawn a new thread on every event.

To Reproduce
The behaviour can be reproduced with the event-stream-tokio.rs example. Notice the new PID in htop in the gif below which changes on every keypress.

How to reproduce [gif]

Peek 2020-06-29 20-47

N.B. In the gif above, core_threads is set to one for clarity (i.e. #[tokio::main(core_threads = 1)]).

Expected behavior
A new thread should not be created on every keystroke.

OS
Ubuntu 20.04 LTS (Linux 5.4.0-37-generic x86_64)

Terminal/Console
Alacritty + tmux.


After investigating this, I thought it may be related to tput because of the following comment in the source code

This can take a really long time, because terminal::size can launch new process (tput) and then it parses its output.

However, this doesn't seem to be the case -- the branch where tput gets called (when /dev/tty is not available) is not taken and at any rate removing the signal handling logic for signal_hook::SIGWINCH doesn't change the behaviour.

@mcobzarenco
Copy link
Author

mcobzarenco commented Jun 29, 2020

Actually, investigating further it seems this may be intended behaviour after all?

// Stream::poll_next can return Poll::Pending which means that there's no
// event available. We are going to spawn a thread with the
// poll_internal(None, &EventFilter) call. This call blocks until an
// event is available and then we have to wake up the executor with notification
// that the task can be resumed.

Is there no way to avoid this? It seems terribly inefficient. I am thinking that at least conceptually, EventStream could be implemented as

  1. an io thread where crossterm calls mio::Poll::poll() on stdin + a waker
  2. the io thread parses and pushes input events to a channel
  3. on dropping the EventStream, the io thread is woken via the waker so it can cleanly exit

// I apologize in advance if this reads like the ramblings of a madman :-) -- I'm new to the codebase -- I'm migrating over from supporting multiple backends to just crossterm because of its much nicer input story (e.g. termion makes it impossible to cleanly exit -- not specific to that crate, but more generally as there's no way to cancel a blocking read on stdin).

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

Successfully merging a pull request may close this issue.

1 participant