-
Notifications
You must be signed in to change notification settings - Fork 4
Fix subscription/removal race in Bus.on() fire-and-forget pattern #451
Copy link
Copy link
Open
Labels
area:busEvent busEvent busbugSomething isn't workingSomething isn't workingsize:smallQuick win, < 1 hourQuick win, < 1 hour
Milestone
Description
Description
Bus.on() spawns an async task for add_listener and immediately returns a Subscription. If cancel() is called before the add task completes, the remove finds nothing in the router, then the add task runs — leaving the listener permanently registered with no way to remove it individually.
remove_all_listeners by owner catches it during shutdown, but the individual subscription handle is broken.
Steps to Reproduce
- Call
sub = bus.on_state_change("light.kitchen", handler=callback) - Immediately call
sub.cancel()before the event loop processes the add task - The listener is added after the cancel, with no way to remove it
Expected Behavior
Cancelling a subscription should reliably remove the listener, even if called before the add task completes.
Acceptance Criteria
-
Subscription.cancel()reliably removes the listener even when called beforeadd_listenercompletes - No permanently orphaned listeners after cancel
- Existing tests pass
Context
Found during post-execution challenge review of bus/scheduler hardening (#437, #412, #414, #436). Pre-existing issue, not introduced by the hardening changes.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:busEvent busEvent busbugSomething isn't workingSomething isn't workingsize:smallQuick win, < 1 hourQuick win, < 1 hour
Projects
Status
Refinement