Fix crash on Linux when testing the archive plugin#641
Conversation
|
@0xTim When time permits, can you check this change on the plugin ? It fixes a race condition that causes the plugin to crash from time to time. |
There was a problem hiding this comment.
Pull request overview
Fixes a CI-only crash on Linux in the AWSLambdaPackager archive plugin by removing Process.terminationHandler output draining and instead stopping readabilityHandler after waitUntilExit(), then draining remaining pipe output.
Changes:
- Removed
Process.terminationHandlerthat performed areadToEnd()on the output pipe. - After
waitUntilExit(), disabledreadabilityHandlerand scheduled a finalreadToEnd()to drain remaining output. - Updated comments to document the Linux race/SIGSEGV rationale.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Read any remaining data from the pipe | ||
| outputQueue.async { outputHandler(try? pipe.fileHandleForReading.readToEnd()) } | ||
|
|
||
| // wait for output to be fully processed | ||
| outputSync.wait() |
There was a problem hiding this comment.
outputSync.wait() is not guaranteed to wait for the final outputQueue.async (or any pending readability-handler enqueues), because outputSync.enter() happens inside outputHandler after the async work has started. If wait() runs before the async block executes, the group count is still 0 and wait() can return early, causing truncated output and potential mutation of outputMutex after output is read. Move the DispatchGroup enter/leave to wrap each outputQueue.async submission (or drain the queue with outputQueue.sync {} / use outputQueue.sync for the final readToEnd).
Fix a rare crash in CI on the archive plugin.
The crash is a race condition in
PluginUtils.swift's execute method. The code set aterminationHandleron theProcessthat calledreadToEnd()on the pipe, while simultaneously thereadabilityHandlercould still be firing on the same pipe's file handle. On Linux (x86_64, Ubuntu 24.04 in CI), this race corrupts memory during Swift runtime metadata resolution (swift_conformsToProtocol, _swift_getGenericMetadata), which manifests as theSIGSEGVwe're seeing in_dispatch_event_loop_drain.The fix:
I removed the
terminationHandlerentirely. SincewaitUntilExit()is already called synchronously, we know the process is done.After
waitUntilExit(), we setreadabilityHandler = nilto stop the async reads, then do one finalreadToEnd()on the output queue to drain any remaining data.This eliminates the race between the readability handler and the termination handler competing over the same file handle.