Repository navigation
Fix Windows rewatch CI flakes from files opened without delete sharing - #9034
Conversation
Unix.openfile opens files on Windows without FILE_SHARE_DELETE unless asked, so while the watcher read lib/watch.lock (every 100 ms) or hashed a source, other processes could not delete or rename it. Removing the lock then failed with "Device or resource busy" and the watcher kept running; Rust's File::open shares delete by default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GtJW7McE7BZqNZGt5VULiK Signed-off-by: Christoph Knittel <ck@cca.io>
A single failed rm left the watcher running into later tests, where the runner later killed it as an orphan. Retry for five seconds, and kill the watcher when it still does not exit so the failure stays in its test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GtJW7McE7BZqNZGt5VULiK Signed-off-by: Christoph Knittel <ck@cca.io>
The retained-parse test now prints watch.log and calls.log when the edit of B does not re-parse A. A watchdog in the parity step reports and stops runaway rescript/bsc processes: four Windows runners lost contact with GitHub during that step, past its timeout, without any log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GtJW7McE7BZqNZGt5VULiK Signed-off-by: Christoph Knittel <ck@cca.io>
Changelog🐛 Bug fix
Semantic Diff4 commits · Full page Open files with delete sharing on Windows314e53f · cknitt + Claude · Oct 25, 2026, 05:42 UTC Unix.openfile opens files on Windows without FILE_SHARE_DELETE unless asked, so while the watcher read lib/watch.lock (every 100 ms) or hashed a source, other processes could not delete or rename it. Removing the lock then failed with "Device or resource busy" and the watcher kept running; Rust's File::open shares delete by default. Retry removing watch.lock and stop a watcher that ignores ita1da0c0 · cknitt + Claude · Oct 25, 2026, 05:43 UTC A single failed rm left the watcher running into later tests, where the runner later killed it as an orphan. Retry for five seconds, and kill the watcher when it still does not exit so the failure stays in its test. Diagnose Windows rewatch CI failures that leave no evidence94ef5ea · cknitt + Claude · Oct 25, 2026, 05:43 UTC The retained-parse test now prints watch.log and calls.log when the edit of B does not re-parse A. A watchdog in the parity step reports and stops runaway rescript/bsc processes: four Windows runners lost contact with GitHub during that step, past its timeout, without any log. ✨ Serialize writes to the compiler call logc5694c7 · cknitt + Claude · Oct 25, 2026, 06:18 UTC · new Parallel domains appended to REWATCH_COMPILER_CALL_LOG through separate handles, and Windows emulates append as seek-then-write, so one domain's line could overwrite another's. The retained-parse test then missed A's parse line (and the initial build's implementation line for A) although A was parsed: the Windows "flake" in that test was a lost log line. |
Parallel domains appended to REWATCH_COMPILER_CALL_LOG through separate handles, and Windows emulates append as seek-then-write, so one domain's line could overwrite another's. The retained-parse test then missed A's parse line (and the initial build's implementation line for A) although A was parsed: the Windows "flake" in that test was a lost log line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GtJW7McE7BZqNZGt5VULiK Signed-off-by: Christoph Knittel <ck@cca.io>
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c5694c7e44
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| rm -f "$WATCHDOG_RUNNING" | ||
| if [ -s "$WATCHDOG_REPORT" ]; then |
There was a problem hiding this comment.
Wait for the watchdog before reading and deleting its report
On Windows, if the parity step finishes while the watchdog is sleeping or collecting process details, removing the sentinel does not stop its current iteration: windows_process_watchdog.ps1 checks the sentinel only before its five-second sleep. This cleanup immediately reads the report and deletes its directory without waiting for PowerShell, so an in-flight watchdog action can be missed and the step can return success despite stopping processes. The watchdog can also continue into subsequent CI steps. Save the background PID and wait for it to finish after removing the sentinel, before inspecting the report or deleting its directory. This also satisfies the scoped process-ownership requirement.
AGENTS.md reference: rewatch-ocaml/AGENTS.md:L29-L31
Useful? React with 👍 / 👎.
rescript
@rescript/belt
@rescript/darwin-arm64
@rescript/linux-arm64
@rescript/linux-x64
@rescript/runtime
@rescript/win32-x64
commit: |
|
Developer playground preview: https://rescript-lang.github.io/rescript/dev-playground/?version=pr-9034 |
Windows-only CI failures (~18 jobs, 2026-10-20 to 10-24) were all in the OCaml rewatch test steps:
rm: cannot remove 'lib/watch.lock': Device or resource busy, then "Watcher process N did not exit". The watcher re-reads the lock every 100 ms throughUnix.openfile, which on Windows doesn't share delete unlessO_SHARE_DELETEis passed. Anrmthat lands during a read fails, and the watcher is left orphaned. Rust'sFile::openshares delete by default, so this started with the OCaml port.mvof a watched directory failed with Permission denied. Same mechanism: the watcher hashes a file inside it.REWATCH_COMPILER_CALL_LOG. Parallel compiler requests each reopen that log in append mode, and on Windows appending is seek-then-write, so one line can overwrite another. The initial build's compile line for A was missing from the same log. So the duplicate-event explanation in Fix watch tests that flake on duplicate change events #8902 was wrong.timeout-minutes: 20, and no log survived.Changes:
File_util.open_for_readingpassesO_SHARE_DELETE(a no-op on Unix). All read-only opens and the lock publisher use it.exit_watcherinrewatch/tests/utils.shretries thermand kills a watcher that still doesn't exit, so it can't run into later tests.watch.logandcalls.logwhen its wait fails.rescript/bscprocesses when one exceeds 3 GB, more than 64 are running, or free memory falls below 1.5 GB. The step then fails with that report instead of the runner dying silently.New tests: a unit test in
file_util_tests.mlrenames and deletes a file held open byopen_for_reading. It only proves anything on the Windows unit-test step. I checked the watchdog wrapper locally with a stubpowershell.exe. The PowerShell script itself first runs on Windows CI.🤖 Generated with Claude Code
https://claude.ai/code/session_01GtJW7McE7BZqNZGt5VULiK