Skip to content

fix: open() after a legacy start() left two producers feeding the queue (review of #4) - #5

Merged
thorwhalen merged 1 commit into
masterfrom
fix/legacy-start-then-open
Sep 22, 2026
Merged

thorwhalen merged 1 commit into
masterfrom
fix/legacy-start-then-open

Conversation

@thorwhalen

Copy link
Copy Markdown
Member

Post-merge refute review of #4.

#4's main change holds: every open() gets its own worker, and is_alive()/join() follow it. The gap is the legacy path it explicitly supports ("a reader started the legacy way, with start() ... falls back to Thread's own"):

reader.start()   # runs in self; _worker stays None
reader.close()   # sets the stop flag; self may still be sleeping
reader.open()    # _stop_previous_worker: _worker is None -> nothing to stop
                 # then clears the stop flag -> the legacy run never sees close()

The result is two producers appending to the same queue with interleaved indices, which _stop_previous_worker's docstring says must not happen. Before #4, this sequence raised RuntimeError: threads can only be started once. Now it degrades silently.

Fix. When there is no _worker but self is running (Thread.is_alive(self)), _stop_previous_worker treats self as the previous worker: it signals it, waits up to reopen_timeout_s, and raises if it does not stop.

Tests.

  • test_open_after_a_legacy_start_leaves_a_single_producer: fails on master, passes here.
  • test_stop_does_not_shadow_thread_internals asserted callable(reader._stop), but Thread._stop was removed in Python 3.13, so that test fails there regardless of the code. It now asserts that no Event shadows the name, which is the property the test protects.

All 7 tests pass locally on py3.10 and py3.13.

Self-reviewed only (the dispatching run disallowed sub-agents).

🤖 Generated with Claude Code

https://claude.ai/code/session_011HSBVhDjRU4apSLcRkavv9

A reader started with start() runs in self and has no _worker, so
open()'s _stop_previous_worker saw nothing to stop, then cleared the stop
flag -- the legacy run never observed close() and kept feeding the queue
next to the new worker. open() now also stops and waits for a run in self.

Also make test_stop_does_not_shadow_thread_internals version-robust:
Thread._stop no longer exists on Python 3.13, so assert that no Event
shadows it instead of asserting the method is there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@thorwhalen
thorwhalen merged commit ebb6f7f into master Sep 22, 2026
12 checks passed
@thorwhalen
thorwhalen deleted the fix/legacy-start-then-open branch September 22, 2026 15:05
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.

1 participant