fix: serialize Messages bridge launches across processes - #274
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs changes before merge. Reviewed September 6, 2026, 12:42 PM ET / 16:42 UTC. ClawSweeper reviewWhat this changesThe PR adds a secure per-container file lock so concurrent imsg processes share one Messages bridge launch, with tests for directory creation and lock release after failure. Merge readiness⛔ Needs changes before merge - 1 item remains The fix remains necessary on current main. The reporter’s native before/after evidence clears the previous proof blocker, and no introduced correctness defect was found. Priority: P1 Review scores
Verification
How this fits togetherimsg’s launcher starts Messages.app with an injected helper that handles advanced messaging commands. CLI and bridge-client launch requests pass through the coordinator before cleanup, process creation, and readiness checks. flowchart TD
A[Concurrent imsg processes] --> B[Launch coordinator]
B --> C[Acquire container file lock]
C --> D{Bridge ready?}
D -->|Yes| E[Reuse running Messages]
D -->|No| F[Clean up and launch Messages]
F --> G[Wait for helper readiness]
G --> H[Release lock]
E --> H
Before merge
Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Keep launch serialization in the shared coordinator so all launch entrypoints reuse one ready bridge, while tracking readiness-timeout behavior separately. Do we have a high-confidence way to reproduce the issue? Yes. The reporter reproduced duplicate native Messages instances in 7/15 concurrent-launch trials on v0.15.1, which matches the fetched main revision; this read-only review did not rerun them. Is this the best way to solve the issue? Yes. Locking the existing shared launch boundary and rechecking readiness is a focused repair that avoids competing launch implementations. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 646ea7af9616. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
History |
|
Reporter of #272 here. I have the machine that produced the original duplicate-instance evidence, so I ran the native after-fix proof this review is asking for, on PR head Environment: macOS 26 (Apple Silicon), SIP disabled, full Xcode 26 with XCTest, real Messages.app and a real injected helper. Paths redacted below. Native concurrent-launch proofHarness: two genuinely independent "$BIN" launch & A=$!
sleep 1.2
"$BIN" launch & B=$!
wait $A; wait $B
pgrep -f "Messages.app/Contents/MacOS/Messages"Control — released 0.15.1 (no cross-process lock), 15 trials: Treatment — this PR at 7/15 → 0/15. These are real The lock is created as specified, owner-only regular file: macOS test suite
These are pre-existing and not caused by this PR. I ran the same three against the base commit So they appear to pass in CI (no live bridge) and fail on any developer machine that actually has the helper injected. Worth a separate issue; it is unrelated to this change.
Why this mattersThe duplicate instances are not cosmetic. Both copies claim off the same v2 queue, so a request claimed by the instance the client is not reading from is consumed and never answered — surfacing as Also worth noting for #273: several control trials show |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
It passes — exit code 0:
Base comparisonSince I had both worktrees, I ran the same target on base Base: 15 violations. This PR: 17. The two additional ones are both For completeness,
So the honest summary is: lint passes, and the change adds two Flagging it only because |
|
Verified head The lock covers readiness recheck, queue cleanup, spawn, and readiness wait in both launch entrypoints. It is owner-only, rejects unsafe lock files, closes on exec, and releases on exceptions and owner exit. Local proof compiled the complete production coordinator and SecurePath into a separate-process harness: main performed two launch operations in 10/10 trials; this head performed one in 10/10. Killing the owner released the lock and allowed the waiter to proceed. All 18 queue/readiness tests pass, including independent launchers and recovery after a throwing launch. Independent branch autoreview against Approved the reviewed fork workflow; full macOS/Linux CI is green on this exact head: https://github.com/openclaw/imsg/actions/runs/34031928047. Recommended landing order includes #279 first (independent CLI test output-capture repair) and #277 (host-independent RPC fixtures). No changelog edit is included here; release notes are consolidated in the final notes PR. Fixes #272. |
Summary
Closes #272.
Behavior proof
A compiled coordinator harness drove two independent launch owners against the same readiness state. With process-local coordination only it recorded two launch operations; with the shared lock it recorded one (
unlocked=2,locked=1). The regression test uses the same independent-launcher composition from an absent container directory, and the failure-path test verifies that a throwing owner releases the lock for the next launcher.The lock is held across readiness re-check, cleanup, spawn, and readiness wait. Because the descriptor uses
O_CLOEXEC, the launched Messages process does not inherit ownership; process exit also releases the kernel lock.Validation
swiftc -frontend -parse Sources/IMsgCore/BridgeLaunchCoordinator.swift Sources/IMsgCore/MessagesLauncher.swift Tests/IMsgCoreTests/IMsgBridgeClientQueueTests.swiftnode --test scripts/build-docs-site.test.mjsmake test-helpergit diff --checkmake testcould not start in the local Command Line Tools-only environment because XCTest was unavailable. Hosted CI remains the full Swift-suite validation. No live Messages relaunch was performed, so the reporter's native duplicate-process evidence remains the live-system proof.Disclosure: AI was used to understand the codebase and review the fix.