Repository navigation
cmux-next: FolderChanges.events() returns once its watches are registered - #26517
Conversation
…ered Post-landing review of #26320: arm() resumed each DispatchSource and returned, but resume() only schedules the kernel registration, and dispatch_source(3) says events before it completes are missed, so a write right after events() returned could still be lost. arm() now waits for every source's registration handler (events() is async), and the loop re-arms the same way before it yields. A new test holds the watches' queue suspended and checks events() returns only after it is let go, and that a write the moment it returns is seen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cc8bff1c3ddb4ec353c5
|
Owned by an agent session · session |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
red: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: green on the base 8acb82a; do not merge until green; see lane-rules |
…terministic Review of the fix: the 200 ms sleep did not guarantee the task ran while the queue was held, so a regression could still pass. Task.immediate runs events() on the test's thread until its first suspension, which with the fix is the wait for registration and without it is never reached before it returns. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cc8bff1c3ddb4ec353c5
|
Found 7 test failures on Blacksmith runners: Failures
|
|
Bead |
… stream Review of the fix: a cancelled caller that never iterates would leave the detached loop holding the watch and its descriptors. events() now cancels the watch and finishes the stream instead of starting the loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-cc8bff1c3ddb4ec353c5
|
Review (codex gpt-6-astra high, next-review): SHIP at 366a8e7 No blocking findings. Reviewed registration readiness, rearming, cancellation, and the updated caller and tests. Validation was limited to the supplied files; tests were not run. |
|
Orphaned: no activity for 15 h, and no lane holds a lease on it. Adopted by the orphan sweep: merged |
|
Review (codex gpt-6-astra high, next-review): SHIP at ce569c4 No blocking findings. |
A newer verdict blocks 61e571c (no independent SHIP at the head).
|
Review (codex gpt-6-astra high, next-review): SHIP at 61e571c No blocking findings. Reviewed the supplied diff and changed files. Tests were not run; access to additional repository code was blocked by the tool approval policy. |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/40975388675 at 43303f7 failed: cmux-next checks (god files, concurrency, crash safety, l10n), cmux-next fleet Release compile. |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/40975576275 at 60a6a31 failed: cmux-next checks (god files, concurrency, crash safety, l10n), cmux-next fleet Release compile. |
|
The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/40977234399 at 817e10c failed: cmux-next checks (god files, concurrency, crash safety, l10n), cmux-next fleet Release compile. |
…ld fix) (#27758) #26517 made FolderChanges.events() async (it returns once its watches are registered); #27223, which landed an hour before it, calls it from the synchronous MachineConsentChanges.events(armed:). Together they stop CmuxNextApp from compiling (JoinConsent+App.swift:222: 'async' call in a function that does not support concurrency; fleet job 549a2bfa50c634b6131799d8). MachineConsentChanges.events(armed:) is async now and awaits it, so the folder watch is registered before the file watches and the armed handshake, as its comment already promised; its callers (the model's watch task and JoinConsentTests) await it. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…atch #26517 made FolderChanges.events() async (it now returns once its watches are registered). #27223 landed alongside it with MachineConsentChanges calling events() synchronously, so feat-cmux-next stopped compiling in Release from 00d6d54 on (cmux-next/compile red on every landing since), and no NEXT nightly can build a newer commit. MachineConsentChanges.events(armed:) is now async and awaits the folder's registration before arming the files, which keeps its documented order; its app caller and the two tests await it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fb75b7af9902231028aa
…atch #26517 made FolderChanges.events() async (it now returns once its watches are registered). #27223 landed alongside it with MachineConsentChanges calling events() synchronously, so feat-cmux-next stopped compiling in Release from 00d6d54 on (cmux-next/compile red on every landing since), and no NEXT nightly can build a newer commit. MachineConsentChanges.events(armed:) is now async and awaits the folder's registration before arming the files, which keeps its documented order; its app caller and the two tests await it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fb75b7af9902231028aa
…atch #26517 made FolderChanges.events() async (it now returns once its watches are registered). #27223 landed alongside it with MachineConsentChanges calling events() synchronously, so feat-cmux-next stopped compiling in Release from 00d6d54 on (cmux-next/compile red on every landing since), and no NEXT nightly can build a newer commit. MachineConsentChanges.events(armed:) is now async and awaits the folder's registration before arming the files, which keeps its documented order; its app caller and the two tests await it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fb75b7af9902231028aa
…atch #26517 made FolderChanges.events() async (it now returns once its watches are registered). #27223 landed alongside it with MachineConsentChanges calling events() synchronously, so feat-cmux-next stopped compiling in Release from 00d6d54 on (cmux-next/compile red on every landing since), and no NEXT nightly can build a newer commit. MachineConsentChanges.events(armed:) is now async and awaits the folder's registration before arming the files, which keeps its documented order; its app caller and the two tests await it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fb75b7af9902231028aa
…atch #26517 made FolderChanges.events() async (it now returns once its watches are registered). #27223 landed alongside it with MachineConsentChanges calling events() synchronously, so feat-cmux-next stopped compiling in Release from 00d6d54 on (cmux-next/compile red on every landing since), and no NEXT nightly can build a newer commit. MachineConsentChanges.events(armed:) is now async and awaits the folder's registration before arming the files, which keeps its documented order; its app caller and the two tests await it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fb75b7af9902231028aa
…atch #26517 made FolderChanges.events() async (it now returns once its watches are registered). #27223 landed alongside it with MachineConsentChanges calling events() synchronously, so feat-cmux-next stopped compiling in Release from 00d6d54 on (cmux-next/compile red on every landing since), and no NEXT nightly can build a newer commit. MachineConsentChanges.events(armed:) is now async and awaits the folder's registration before arming the files, which keeps its documented order; its app caller and the two tests await it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-fb75b7af9902231028aa
|
Shipped in:
|
|
Shipped in:
|
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Fix-forward for #26320 (squash 39d216b), from its post-landing review, which answered FIX:
What changes
FolderChanges.events()is nowasync.arm()gives every dispatch source a registration handler and waits for each one before it returns, so a change made afterevents()returns is always delivered. The wait ends early if the calling task is cancelled, so a cancelled caller never hangs.BackdropCatalogStore(the only production caller) awaitsevents().events()cancels the watch and returns a finished stream. The detached loop never holds descriptors for a caller that will not iterate.FolderChangesTests.eventsReturnsOnlyOnceTheWatchesAreRegistered. An internal init sets the queue the sources target. The test holds that queue suspended so no registration handler can run, and startsevents()withTask.immediate, so it runs synchronously up to its first suspension. It checks two things:events()returns only after the queue is resumed (from an ordered step log), and a write made the moment it returns produces an element. There is no sleep. With the fix the test cannot fail, however the threads are scheduled. Without the wait,events()has no suspension point and returns before the test resumes the queue, so the test fails every time.armed.cancel().No capture: no visible UI change; this only changes when the folder watch behind the wallpaper catalog reports that it is ready.
Risk
Low. The change is contained to the folder watch behind the wallpaper catalog.
events()now waits for kernel registration before returning, which is sub-millisecond.Verification
Fleet runs pending; this section is updated with their results.
Agent session: agent session
🤖 Generated with Claude Code