Skip to content

fix: propagate EventStream poll errors - #1070

Open
alurm wants to merge 1 commit into
crossterm-rs:masterfrom
alurm:codex/event-stream-terminal-error
Open

fix: propagate EventStream poll errors#1070
alurm wants to merge 1 commit into
crossterm-rs:masterfrom
alurm:codex/event-stream-terminal-error

Conversation

@alurm

@alurm alurm commented Jul 20, 2026

Copy link
Copy Markdown

Summary

  • Stop EventStream's blocking worker from retrying indefinitely after a polling error.
  • Preserve the error and wake the async consumer so that the next poll_next returns it.
  • Suppress polling errors caused by waking the worker during normal EventStream shutdown.
  • Add an entry to the changelog.

Motivation

EventStream already exposes io::Result<Event>, and errors from its immediate non-blocking poll are returned to the consumer. However, errors from the blocking poll on its background thread were ignored and retried indefinitely.

That could leave the worker spinning after a terminal failure instead of reporting the error to the stream consumer.

Related work

This is independent of #1067, which makes the Unix event source report an error when its TTY disappears. The two changes are complementary: #1067 detects the disconnected TTY, while this PR propagates that error through EventStream.

Testing

The tests cover:

  • not starting another poll after shutdown;
  • suppressing an error when shutdown occurs during a poll;
  • polling only once after a real error, storing that error, and waking the stream consumer.

Commands run:

cargo fmt --all -- --check
cargo clippy --all-features -- -D clippy::all
cargo test --all-features
cargo test --no-default-features --features "use-dev-tty events event-stream bracketed-paste"

Assisted by Codex:gpt-5.6-sol.

Preserve errors from the blocking EventStream poll and wake the async
consumer instead of retrying indefinitely. This allows terminal
disconnection errors to reach the stream consumer.

Assisted-by: Codex:gpt-5.6-sol
Comment thread src/event/stream.rs
task.stream_wake_task_executed
.store(false, Ordering::SeqCst);
task.stream_waker.wake();
run_stream_wake_task(task, || internal::poll(None, &EventFilter));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In C, the language greatly encouraged callees to be above callers, so you could generally read from the bottom up. Rust doesn't have that restriction, so some people order things top down (which I don't like, but I'm letting that go).

LLMs just do not care about human readers at all and so will spray out code in all directions, which can be hard for a human to read. I think people should pick an order and try to force the LLM to stick to it. If A calls B calls C, the reviewer should see an order that makes sense (A-B-C or C-B-A, not A-C-B).

(This is not an anti-LLM rant.)

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 this pull request may close these issues.

2 participants