Skip to content

reflex run --json: the 30 s drain cap can end the stream mid-record, and a consumer that stops reading blocks shutdown forever #7510

Description

@masenf

Severity: LOW. #7428 is strictly better than 0.10.0a2. Confirmed by an independent verifier (pre-release finding A3-08).

#7428 itself works. With a consumer reading 40 lines/s, Ctrl-C or SIGTERM exits in 6.5–6.7 s with rc 0, no lines lost and no invalid JSON. a2 lost 49–63 lines plus a truncated record.

Truncated last record. With a slow consumer (6 lines/s, or 2 KB/s), the 30 s cap fires as designed. The stream then ends inside a record with no newline, e.g. {"timestamp": "...", "level". A line-by-line parser sees one invalid record, and 82–356 lines are never delivered.

Cause: the converted ~135 KB batch goes out in one blocking write on a daemon thread (_OutputPump._write, log.py:420-437, via _write_all :365-374, thread :389). The main thread calls exit_group(0) 30.07 s after the child exited, in the middle of that write.

Second trigger. A second Ctrl-C during the drain exits immediately with rc 1. It prints a plain-text Aborted! on stderr and leaves a 168 B partial record. KeyboardInterrupt is caught only around proc.wait() (:520-526).

Consumer that stops reading. If the consumer stops reading entirely, shutdown blocks forever on a3, a2 and 0.9.12. The cap only starts after the child exits, so the comment at log.py:278 ("even when a consumer blocks every write") overstates what it does.

Fix ideas

  • write in bounded chunks and stop only at record boundaries when the cap fires;
  • handle the second interrupt the same way;
  • start the cap from the stop request rather than from the child's exit.

Repro: a3_upgrade/bin/json_matrix.sh a3 a3 TERM-pid:6 (dir). Evidence: A3-08 in FINDINGS.md.

Activity

  1. added theissue type on Oct 8, 2026
  2. linear-code commented on Oct 8, 2026

    @linear-code
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

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions