Skip to content

Commit 4abcade

Browse files
fix(audience): volatile _disposed + tighter shutdown ordering
Addresses cursor[bot] review comment on EventQueue.cs:29. - Mark _disposed as volatile so the shutdown signal is visible across threads. On weakly-ordered architectures (ARM — Apple Silicon, etc.) the C# memory model does not guarantee a non-volatile write is eventually observed by other threads without a fence. - Reorder Shutdown: set _disposed=true first, before canceling the drain thread. The shutdown flag being the first observable state change is a safer ordering and makes the lifecycle easier to reason about. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b9ebac5 commit 4abcade

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

src/Packages/Audience/Runtime/Transport/EventQueue.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ internal sealed class EventQueue : IDisposable
2626
private readonly Thread _drainThread;
2727
private readonly ManualResetEventSlim _flushGate = new ManualResetEventSlim(false);
2828

29-
private bool _disposed;
29+
// Volatile so all threads see the shutdown signal immediately.
30+
private volatile bool _disposed;
3031

3132
/// <param name="store">Pre-created <see cref="DiskStore"/> for this queue.</param>
3233
/// <param name="flushIntervalSeconds">How often to drain to disk regardless of batch size.</param>
@@ -73,11 +74,18 @@ internal void FlushAsync()
7374
internal void Shutdown()
7475
{
7576
if (_disposed) return;
77+
78+
// Stop accepting new events first — closes the race window where
79+
// events enqueued between Cancel and final drain would be lost.
80+
_disposed = true;
81+
82+
// Signal the drain thread to exit, then wait for it.
7683
_cts.Cancel();
77-
_flushGate.Set(); // Wake drain thread so it exits promptly
84+
_flushGate.Set();
7885
_drainThread.Join(TimeSpan.FromSeconds(5));
79-
DrainMemoryToDisk(); // Final drain after thread stops
80-
_disposed = true;
86+
87+
// Final drain: anything enqueued before _disposed was set.
88+
DrainMemoryToDisk();
8189
}
8290

8391
// -----------------------------------------------------------------

0 commit comments

Comments
 (0)