diff --git a/tests/03-full-cycle-cs/Program.cs b/tests/03-full-cycle-cs/Program.cs index 416c5c2..dabe81f 100644 --- a/tests/03-full-cycle-cs/Program.cs +++ b/tests/03-full-cycle-cs/Program.cs @@ -96,7 +96,7 @@ try int beepFrames = 0; int recordOffset = 0; short[] recordBuf = null!; // assigned on BEEPING→RECORDING transition - var playbackDone = new PlaybackDoneFlag(); + PlaybackDoneFlag? playbackDone = null; try { @@ -157,6 +157,7 @@ try { try { + playbackDone = new PlaybackDoneFlag(); FireAndForgetPlayback(device, recordBuf, playbackDone); } catch (Exception ex) @@ -177,7 +178,7 @@ try case State.Playback: { // Discard input during playback (gate the detector). - if (playbackDone.Consume()) + if (playbackDone!.Consume()) { model.Reset(); Console.WriteLine("[state] IDLE"); @@ -287,7 +288,8 @@ static void FireAndForgetBeep(int device, short[] beepBuffer) // 2 s timeout so a failed callback (which PortAudio silently swallows // and would leave 'done' unset) eventually releases the stream + handle // instead of leaking them for the process lifetime. - done.Wait(TimeSpan.FromSeconds(2)); + if (!done.Wait(TimeSpan.FromSeconds(2))) + Console.Error.WriteLine("[error] beep playback timed out — callback may have faulted"); Thread.Sleep(200); stream.Stop(); stream.Dispose(); @@ -348,7 +350,8 @@ static void FireAndForgetPlayback(int device, short[] recordBuf, PlaybackDoneFla Task.Run(() => { // Same 2 s safety timeout as the beep cleanup. - done.Wait(TimeSpan.FromSeconds(2)); + if (!done.Wait(TimeSpan.FromSeconds(2))) + Console.Error.WriteLine("[error] recording playback timed out — callback may have faulted"); Thread.Sleep(200); stream.Stop(); stream.Dispose();