Summary
Job Compiled extensions (Windows), step "Verify relocated compiled extensions", test scripts/compiled-extension-load.test.ts (unnamed, ~14.6s) fails after scripts/build-binaries.sh returns 0: renameSync of the just-built release/windows-x64 directory to the relocated fixture path throws EPERM: operation not permitted.
Where
scripts/compiled-extension-load.test.ts beforeAll (~line 50):
const build = spawnSync("bash", ["scripts/build-binaries.sh", "--skip-install", "--skip-build", "--platform", platform, "--out", ...]);
expect(build.status, ...).toBe(0);
renameSync(join(release, platform), relocated);
relocated is .../relocated # % binary (Windows-legal special characters from compiledExtensionPlatform).
Reproduction
Intermittent on windows-latest. Same tree can pass or fail.
Newer main runs at c7b41b1bf … 9432e4e10 passed, so this is not branch-specific.
Expected
After spawnSync reaps build-binaries.sh, the test can move the platform directory to the relocated path and then load compiled extensions from that path. A transient Windows sharing violation is retried until the handle is gone, or the test fails with the original EPERM/EBUSY/ENOTEMPTY attached if the directory never becomes movable.
Actual
error: EPERM: operation not permitted, rename '...\\release\\windows-x64' -> '...\\relocated # % binary'
at <anonymous> (scripts/compiled-extension-load.test.ts:50:2)
build.status === 0. The unnamed test dies in beforeAll in ~15s.
Root cause hypothesis
Windows MoveFileEx returns EPERM/EBUSY while any handle still holds the directory or a just-written executable. build-binaries.sh compiles pi.exe, zips/unzips the tree, then smoke-standalone-binary.mjs actually runs that pi.exe from the directory the test immediately renames. spawnSync waits for bash, but a grandchild, an antivirus scan, or the image mapping of the just-run executable can still hold the tree for a short window. A single renameSync with no retry turns that window into a flake.
Scope and acceptance criteria
- The test still relocates the built tree away from
release/<platform> and still asserts compiled-extension load from the special-character path. No .skip, no retry: N on the test, no fixed sleep, no loosened assertion.
- Rename retries only on
EPERM / EBUSY / ENOTEMPTY, with short backoff and a hard deadline. Deadline expiry fails loudly with the underlying error attached (cause). Other errno codes throw immediately.
- Unit tests: injected
renameSync throws EPERM twice then succeeds; injected renameSync throws EPERM forever and the helper fails with the original error attached. Clock/sleep injected so the tests are deterministic.
Compiled extensions (Windows) is green on three consecutive runs of the same head.
Related
Same class as other Windows sharing-violation flakes: the operation is correct; the handle has not closed yet.
Summary
Job
Compiled extensions (Windows), step "Verify relocated compiled extensions", testscripts/compiled-extension-load.test.ts(unnamed, ~14.6s) fails afterscripts/build-binaries.shreturns 0:renameSyncof the just-builtrelease/windows-x64directory to the relocated fixture path throwsEPERM: operation not permitted.Where
scripts/compiled-extension-load.test.tsbeforeAll(~line 50):relocatedis.../relocated # % binary(Windows-legal special characters fromcompiledExtensionPlatform).Reproduction
Intermittent on
windows-latest. Same tree can pass or fail.feat/omp-s2-20260913at249225d72(pure merge ofmainat5fb5d638d): https://github.com/code-yeongyu/senpi/actions/runs/34982822646mainat5fb5d638d: https://github.com/code-yeongyu/senpi/actions/runs/34955867964Newer
mainruns atc7b41b1bf…9432e4e10passed, so this is not branch-specific.Expected
After
spawnSyncreapsbuild-binaries.sh, the test can move the platform directory to the relocated path and then load compiled extensions from that path. A transient Windows sharing violation is retried until the handle is gone, or the test fails with the originalEPERM/EBUSY/ENOTEMPTYattached if the directory never becomes movable.Actual
build.status === 0. The unnamed test dies inbeforeAllin ~15s.Root cause hypothesis
Windows
MoveFileExreturnsEPERM/EBUSYwhile any handle still holds the directory or a just-written executable.build-binaries.shcompilespi.exe, zips/unzips the tree, thensmoke-standalone-binary.mjsactually runs thatpi.exefrom the directory the test immediately renames.spawnSyncwaits for bash, but a grandchild, an antivirus scan, or the image mapping of the just-run executable can still hold the tree for a short window. A singlerenameSyncwith no retry turns that window into a flake.Scope and acceptance criteria
release/<platform>and still asserts compiled-extension load from the special-character path. No.skip, noretry: Non the test, no fixed sleep, no loosened assertion.EPERM/EBUSY/ENOTEMPTY, with short backoff and a hard deadline. Deadline expiry fails loudly with the underlying error attached (cause). Other errno codes throw immediately.renameSyncthrowsEPERMtwice then succeeds; injectedrenameSyncthrowsEPERMforever and the helper fails with the original error attached. Clock/sleep injected so the tests are deterministic.Compiled extensions (Windows)is green on three consecutive runs of the same head.Related
Same class as other Windows sharing-violation flakes: the operation is correct; the handle has not closed yet.