Fix SIGABRT on shutdown: serialize encoder encode/flush/stop - #3
Merged
Merged
Conversation
LiveAudioServer.stop() (a Swift task) stopped the MP3 and AAC encoders while the stdin-pcm-reader thread was still encoding, sending its EOF flush, and then calling stop() again in its own epilogue. Nothing serialized these, so AudioConverterReset/Dispose and lame_encode_flush/ lame_close ran concurrently on the same handle: "pointer being freed was not allocated" in aacClose, or a LAME assert in format_bitstream. - AACEncoder / MP3Encoder: an NSLock serializes encode, flush and stop; stop() is idempotent and later encode() calls are no-ops. - AACEncoder.stop() no longer resets before disposing (reset only discards buffered input and emits nothing). - MP3Encoder flushes at most once (EOF flush and stop no longer both run). - CLI: graceful shutdown is one-shot, so the --exit-with-parent watchdog (fires every 0.5 s) can't start a second shutdown that exit(0)s while the first is still tearing down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
LiveAudioServer crashed with SIGABRT nearly every time AntennaHead quit or restarted it (42 crash reports since 2026-09-18). There were two signatures:
AudioConverterReset→aacClose→DeleteLoopKernel→ pointer being freed was not allocatedlame_encode_flush→format_bitstreamassertIn every report, two threads were tearing down the same encoder at once:
LiveAudioServer.stop()(Swift task) calledencoder.stop()while thestdin-pcm-readerthread was still running. That thread sends an EOFencode(count: 0)→flush()and then callsstop()again in its epilogue. Nothing serialized them.Fix
AACEncoder/MP3Encoder: anNSLockserializes encode, flush, and stop.stop()is idempotent, andencode()does nothing after stop.AACEncoder.stop()no longer resets before disposing. Reset only discards buffered input.MP3Encoderflushes at most once.--exit-with-parentwatchdog fires every 0.5 s and could start a second shutdown that calledexit(0)mid-teardown.Verification
swift build, andswift testpasses all 110 tests.--keep-alive --filler-mode silence, UDP input): old binary crashed 19/40 (mono) and 14/20 (stereo); new binary 0/120.--exit-with-parent): old binary shut down cleanly 2/15 times, new binary 15/15..ips.🤖 Generated with Claude Code