Skip to content

Commit cc7d275

Browse files
Fix DateFormatter thread safety and stale delegate race
- Replace DateFormatter with thread-safe ISO8601DateFormatter (log() is called from both main and background threads) - Nil out old session's sample buffer delegate before dispatching stopRunning() to prevent stale callbacks from corrupting new session's sampleCount Addresses Devin review findings on PR #2.
1 parent c2b2e6b commit cc7d275

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

Sources/MicWarm/main.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import Foundation
55

66
// MARK: - Logging
77

8-
let logDateFormatter: DateFormatter = {
9-
let f = DateFormatter()
10-
f.dateFormat = "HH:mm:ss.SSS"
8+
// ISO8601DateFormatter is thread-safe, unlike DateFormatter.
9+
// log() is called from both main and background threads (stopRunning watchdog).
10+
let logDateFormatter: ISO8601DateFormatter = {
11+
let f = ISO8601DateFormatter()
12+
f.formatOptions = [.withTime, .withFractionalSeconds]
13+
f.timeZone = .current
1114
return f
1215
}()
1316

@@ -202,6 +205,13 @@ class MicKeeper: NSObject, AVCaptureAudioDataOutputSampleBufferDelegate {
202205
#if false // Enable for instrumented debugging
203206
old.removeObserver(self, forKeyPath: "running")
204207
#endif
208+
// Disconnect the old session's sample buffer delegate immediately so stale
209+
// callbacks don't increment the new session's sampleCount.
210+
for output in old.outputs {
211+
if let audioOutput = output as? AVCaptureAudioDataOutput {
212+
audioOutput.setSampleBufferDelegate(nil, queue: nil)
213+
}
214+
}
205215
// Stop the old session on a background thread. stopRunning() can deadlock
206216
// if the session's Bluetooth device has already disconnected (CoreAudio hangs
207217
// in AudioObjectRemovePropertyListener waiting on a dead device).

0 commit comments

Comments
 (0)