Skip to content

.cat --follow / .last --follow ignore interrupts: cancelled followers park until the next matching frame #164

Description

@cablehead

Summary

.cat --follow and .last --follow don't observe the caller's interrupt signal. When the consumer of a follow stream is cancelled (for example, an http-nu SSE client disconnects), the reader thread stays parked in rx.blocking_recv() until the next frame matching its topics arrives. On a quiet topic that can be indefinitely.

Where

cross-stream 0.14.0:

  • src/nu/commands/cat_command.rs, the follow branch (around line 170): rx.blocking_recv() inside a ListStream built with Signals::empty()
  • src/nu/commands/last_command.rs, lines 95–99: the same pattern

The comment says the consumer dropping the ListStream cancels the producer. But the consumer only gets to drop it after blocking_recv() returns, which needs a frame.

Impact

http-nu 582503c ("release a streaming request's thread when its client disconnects") now interrupts a request's job when its client goes away. For handlers that use .cat --follow, the thread is still held until a matching frame wakes the follower. Streams following rare topics can hold a thread for the life of the server.

Repro

http-nu c7383e2 (cross-stream 0.14.0), with a handler whose SSE stream follows .cat --follow -T "seat.verdict,here,here.list", on an 8-core box:

threads
before 18
20 SSE streams open 78
3s after all 20 clients disconnect, no new frames 38 (one parked follower per stream)
0.5s after appending a single matching frame 18

The release happens only when a matching frame arrives.

Suggested fix

Have the follow branches of .cat and .last observe the caller's interrupt, for example by building the ListStream with engine_state.signals() and waiting on the channel in short slices (such as 100ms) with a check of signals.interrupted() between them. That's the approach http-nu 582503c took for .bus sub. Disconnected followers would then be released within about 100ms, whatever the traffic.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions