Repository navigation
Conversation
036e2f4 to
c1e6e39
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c1e6e39. Configure here.
| case status := <-ch: | ||
| case status, ok := <-ch: | ||
| if !ok { | ||
| return false |
There was a problem hiding this comment.
WaitFor misses Off after stop
Medium Severity
Stop() now sets Off without broadcasting, then closes listener channels. WaitFor treats that close as failure and returns false without reading the current status, so a wait already in progress for DataSourceStateOff fails even though the data system did reach Off.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c1e6e39. Configure here.
There was a problem hiding this comment.
This was already the case before #489, and this PR just reverts to that previous behavior. We should address broadcasting Off, but in a later PR.
kinyoklion
left a comment
There was a problem hiding this comment.
Approved with consideration of 505.


Summary
#489 made
FDv2.Stop()broadcast anOffstatus after its goroutines exit. A broadcast does a blocking send to each listener channel, which buffers 10 values. If an application listener stops reading while its buffer is full,Stop()blocks forever. That hangsLDClient.Close(), andGetStatus()hangs with it, because the send ran under the status lock.The hazard predates #489. Any status update can block the same way while the data system runs, and the broadcaster holds its lock during the send. So removing the stuck listener also blocks.
This PR:
RemoveListenerandCloseunblock a send to a full listener. Listeners that keep reading still get every value, in order. No broadcast drops events.GetStatus()no longer waits on a listener.OfffromFDv2.Stop(). The status still changes toOff, and listeners learn of shutdown when their channels close.WaitForthat only existed to work around the blocking removal.WaitForreturnfalsewhen its listener channel closes, in both FDv1 and FDv2. Before, aWaitForstill running atClose()spun on the closed channel until its timeout.Note
Overview
Fixes deadlocks when a data-source status listener stops reading while its buffered channel is full—
LDClient.Close(),Stop(),RemoveListener, andGetStatus()could block because broadcasts sent under locks.The shared
Broadcasternow sends without holding the subscriber list lock, and each subscriber uses adonesignal soRemoveListener/Closecan abort an in-flight send to a full channel. Active readers still receive every event in order.FDv2 mirrors FDv1 by broadcasting status after releasing the status mutex via
maybeUpdateStatus.Stop()sets state toOfflocally but does not broadcastOff; shutdown is signaled by closing listener channels.WaitForno longer spins drain goroutines and returnsfalsewhen the listener channel closes.Reviewed by Cursor Bugbot for commit c1e6e39. Bugbot is set up for automated code reviews on this repo. Configure here.