fix(media): bound ffmpeg conversion wait with a timeout#176
Conversation
runConversionProcess called waitUntilExit with no deadline, so a hung ffmpeg blocked attachment conversion indefinitely. Poll isRunning with a default 60s timeout and terminate/kill the process when it expires. Signed-off-by: Sebastien Tardif <[email protected]>
|
Codex review: needs maintainer review before merge. Reviewed July 12, 2026, 6:29 PM ET / 22:29 UTC. Summary Reproducibility: yes. at source level with high confidence: current main waits for ffmpeg indefinitely, and the PR provides a concrete hung-converter path plus after-fix live output showing bounded completion. The failing current-main path was not executed in this read-only Linux review environment. Review metrics: 2 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land a monotonic converter deadline after the feature owner confirms that 60 seconds is an acceptable maximum, or selects a better internal bound, while retaining the existing success-path and hung-process proof. Do we have a high-confidence way to reproduce the issue? Yes, at source level with high confidence: current main waits for ffmpeg indefinitely, and the PR provides a concrete hung-converter path plus after-fix live output showing bounded completion. The failing current-main path was not executed in this read-only Linux review environment. Is this the best way to solve the issue? Yes, conditionally. A monotonic deadline with process reaping is a narrow and maintainable fix, but the feature owner should explicitly accept or adjust the proposed 60-second compatibility boundary. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against b5b7464bc748. Label changesLabel justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (2 earlier review cycles) |
Bound converter waits with ContinuousClock so wall-clock jumps cannot stretch the limit, best-effort terminate the process group, and use exec sleep in the hung fixture so the Process PID is the sleeper. Signed-off-by: Sebastien Tardif <[email protected]>
|
@clawsweeper re-review Updated proof: monotonic ContinuousClock deadline, process-group terminate, exec-based hung fixture, and real ffmpeg CAF→m4a terminal output plus production helper hung bound (status 143 in ~0.63s). |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Maintainer repair pushed in The repair moves the timeout regression out of an over-limit test file, strengthens the exact timeout result, and fixes descendant cleanup when the converter leader exits on SIGTERM while a child ignores it. Exact-head proof at
AutoReview:
Live built CLI attachment-history proof remains blocked on this worker because its parent process lacks Full Disk Access. The contributor's PR body retains real ffmpeg and production-helper proof. |
|
Landed with the 60-second converter ceiling accepted as the default: an optional conversion failure is strictly better than an indefinite CLI/RPC hang, the constant is documented and trivially adjustable, and the process-tree cleanup is regression-tested against TERM-ignoring descendants. Changelog entry added on main. |
What Problem This Solves
AttachmentResolver.runConversionProcessstarted ffmpeg and blocked onprocess.waitUntilExit()with no deadline. A hung converter stalled attachment metadata resolution indefinitely when unsupported media conversion was enabled.Evidence
Patch
ContinuousClockdeadline (default 60s).exec sleep 30so the Process PID is the sleeper (no orphaned shell child).Real ffmpeg success (production conversion args)
CAF generated with ffmpeg, then converted with the same flags
AttachmentResolveruses (-nostdin -y -i … -c:a aac -b:a 128k):Production helper path (AttachmentResolver.metadata + runConversionProcess)
On macOS with Homebrew ffmpeg on PATH, calling the patched
AttachmentResolver.metadata(… convertUnsupported: true)for the generated CAF:143is128 + SIGTERMfrom the timeout path; hungexec sleep 30returned in under 1s instead of blocking 30s.Hung bound (exec sleep fixture)
Real behavior proof
Behavior or issue addressed: Unbounded
waitUntilExiton ffmpeg conversion could hang attachment metadata forever; conversions are now deadline-bounded and reaped.Real environment tested: macOS arm64, ffmpeg 8.1.2 (Homebrew
/opt/homebrew/bin/ffmpeg), imsg branchfix/ffmpeg-conversion-timeoutat tip after monotonic/process-group fix.Exact steps or command run after this patch:
Evidence after fix: terminal output above; real m4a produced; hung path returns status 143 in ~0.63s.
Observed result after fix: Successful CAF→m4a conversion via the same args and metadata path; deliberately hung converter exits within the configured bound instead of sleeping 30s.
What was not tested: Live Messages.app chat history with SIP disabled; conversions that legitimately need more than 60s.
Test plan
swift test --filter attachmentResolverConversionTimesOutOnHungConverterswift test --filter attachmentResolverConversionDoesNotBlockOnConverterOutput