Skip to content

StatusInfoReader cannot be re-opened after close() (SourceReader contract violation) #1

Description

@thorwhalen

Found while modernizing this repo's packaging (PR pending on claude/rollout-modernize).

Symptom

SourceReader's documented contract allows a reader to be closed and re-opened — its own class docstring demonstrates exactly that, with open_count reaching 2 on the second with block. StatusInfoReader cannot do this:

from pchealthstream2py.pchealth import StatusInfoReader
import time

r = StatusInfoReader(read_interval_ms=50)
with r:
    time.sleep(0.3)
with r:              # RuntimeError: threads can only be started once
    time.sleep(0.3)

Cause

StatusInfoReader is a threading.Thread (it subclasses both SourceReader and threading.Thread), and open() calls self.start(). A Thread object can only be started once, so the second open() always raises.

Suggested fix

Stop being a thread and have one instead: keep the polling loop in a plain function (or keep run() as the target) and have open() create a fresh threading.Thread(target=..., daemon=True) each time, storing it on the instance; close() sets the stop event and (optionally) joins it. That makes open/close/open work, keeps the buffering behaviour identical, and removes the remaining friction of inheriting Thread's API surface (start, join, is_alive, name, ...) into what is really a SourceReader.

This is a behaviour-visible change (isinstance(reader, threading.Thread) becomes False), which is why it was left out of the packaging-modernization PR rather than bundled into it.

Related, already fixed on claude/rollout-modernize

  • the stop flag was named _stop, shadowing threading.Thread._stop and making join() raise TypeError: 'Event' object is not callable;
  • _index / _data / _stop / _bt were class attributes, so all instances shared one queue and one stop flag.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions