test(build): the make_game checks let go of the work folder's lock, so Windows can delete their temporary folders #804

Open
d4nkn3ss wants to merge 1 commit from d4nkn3ss/Longshot:fix/test-work-lock-windows into main
Contributor

Type: test · Risk: low · Tested on: Windows 11, RTX 3080 · Needs: none

Why

On Windows, five of the builder's game-free checks have errored on main since #630 (one build at a time in a work folder): 41 errors in all, each PermissionError: [WinError 32] ... work\make_game.lock. They run make_game.main() in their own process with the work folder in a temporary directory. main() now keeps make_game.lock open for the rest of the process, and Windows can't delete a folder holding an open file, so every test's clean-up fails. The noise hides real failures in those checks on Windows. I searched the tracker (forge.py issue list --state all) and found no issue for it.

What changed

make_game.py gets release_work(), which lets go of the work folder's lock if this process holds one. The five checks call it before their temporary folders are removed. A build doesn't change: its lock still goes when its process ends.

  • nx2/make_game.py: release_work(), also used by lock_work() where it let go of a lock on another folder (the same two lines, now in one place).
  • tests: test_cpp_preflight.py, test_make_game_prepare.py (both test classes), test_missing_nup.py, test_make_game_cache.py and test_linux_preflight.py register release_work as a clean-up after the temporary folder's, so it runs first. They use getattr(..., "release_work", lambda: None) because their LONGSHOT_*_TEST_SOURCE overrides can point at a make_game.py from before #630, which has no lock.

Measurements

Verdict: passes: the 41 WinError 32 errors are gone. test_cpp_preflight, test_make_game_prepare and test_missing_nup now pass on Windows. test_make_game_cache and test_linux_preflight keep only the shipped-profile failures that #592 fixes, and with that PR's diff on top of this one both pass.

Hardware: Windows 11 Pro 26300, RTX 3080 10 GB, i9-12900K, 64 GB; Python 3.12, llvm-mingw from the Longshot Builder
Scene: none (game-free checks)
Method: python -I -B tests/run_all.py from PowerShell, once on each commit; the failing checks and their unittest summaries compared
How to reproduce: on Windows, python -I -B tests/run_all.py on main and on this branch

Before: main @ aa95d35f After: this PR @ dcc30ba2
test_cpp_preflight.py errors=1 pass
test_make_game_prepare.py errors=1 pass
test_missing_nup.py errors=8 pass
test_make_game_cache.py failures=6, errors=14 failures=6 (#592's); pass with #592 on top
test_linux_preflight.py failures=1, errors=17 failures=1 (#592's); pass with #592 on top
test_work_lock.py pass pass
run_all.py in all 541 passed, 17 failed, 35 skipped 544 passed, 14 failed, 35 skipped
main @ aa95d35f:
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: '...\longshot-missing-nup-f8t74nau\work\make_game.lock'
FAIL       1.4s  tests/test_make_game_cache.py      FAILED (failures=6, errors=14)
FAIL       3.0s  tests/test_linux_preflight.py      FAILED (failures=1, errors=17, skipped=1)

this PR @ dcc30ba2:
pass       2.9s  tests/test_cpp_preflight.py
pass       0.7s  tests/test_make_game_prepare.py
pass       0.9s  tests/test_missing_nup.py
pass       0.8s  tests/test_work_lock.py
FAIL       1.6s  tests/test_make_game_cache.py      FAILED (failures=6)
FAIL       4.3s  tests/test_linux_preflight.py      FAILED (failures=1, skipped=1)

this PR + #592's diff:
make_game_cache => Ran 17 tests | OK
linux_preflight => Ran 19 tests | OK (skipped=1)

Flags and settings

None

Testing

Tested: python -I -B tests/run_all.py from PowerShell on Windows 11, on main @ aa95d35f and on this PR @ dcc30ba2 (numbers above). The 14 checks that fail here fail on main too: test_appimage_player_build (#624), test_cpm_discovery (#561), test_crash_dialog (#626), test_env_on and test_readback_late (#622), test_lift_cleanup_error (#623), test_linux_preflight and test_make_game_cache (#592), test_oot_state_tap, test_options_budget_once, test_release (no openssl on PATH, #144), test_tested_configurations, test_vk_pgo, test_walk_key (#537). test_work_lock.py passes, so lock_work() behaves as before with release_work() inside it. test_make_game_cache.py and test_linux_preflight.py were run again with #592's diff applied on top: both pass.

Not tested:

  • Linux: there an open file doesn't stop its folder being deleted, so these checks didn't fail. The change is portable Python. I didn't run it there.
  • A real build: main() and the CLI are unchanged; the lock is still taken where it was and goes with the process.

Must be tested: None. The game-free checks cover the change.

Risks

What could break: nothing for a player: no build calls release_work(). A check that wanted the lock held after its test finished would lose it, and none does.

Turning it off: revert the commit.

Compatibility: Nothing changes: saves, options, the caches, the vk ABI and the builder's behaviour are untouched.

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • A check under tests/ that reads changed source updated in this PR, not weakened.

🤖 Generated with Claude Code

**Type:** test · **Risk:** low · **Tested on:** Windows 11, RTX 3080 · **Needs:** none ## Why On Windows, five of the builder's game-free checks have errored on main since https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/630 (one build at a time in a work folder): 41 errors in all, each `PermissionError: [WinError 32] ... work\make_game.lock`. They run `make_game.main()` in their own process with the work folder in a temporary directory. `main()` now keeps `make_game.lock` open for the rest of the process, and Windows can't delete a folder holding an open file, so every test's clean-up fails. The noise hides real failures in those checks on Windows. I searched the tracker (`forge.py issue list --state all`) and found no issue for it. ## What changed `make_game.py` gets `release_work()`, which lets go of the work folder's lock if this process holds one. The five checks call it before their temporary folders are removed. A build doesn't change: its lock still goes when its process ends. - nx2/make_game.py: `release_work()`, also used by `lock_work()` where it let go of a lock on another folder (the same two lines, now in one place). - tests: `test_cpp_preflight.py`, `test_make_game_prepare.py` (both test classes), `test_missing_nup.py`, `test_make_game_cache.py` and `test_linux_preflight.py` register `release_work` as a clean-up after the temporary folder's, so it runs first. They use `getattr(..., "release_work", lambda: None)` because their `LONGSHOT_*_TEST_SOURCE` overrides can point at a `make_game.py` from before #630, which has no lock. ## Measurements **Verdict:** passes: the 41 `WinError 32` errors are gone. `test_cpp_preflight`, `test_make_game_prepare` and `test_missing_nup` now pass on Windows. `test_make_game_cache` and `test_linux_preflight` keep only the shipped-profile failures that https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/592 fixes, and with that PR's diff on top of this one both pass. Hardware: Windows 11 Pro 26300, RTX 3080 10 GB, i9-12900K, 64 GB; Python 3.12, llvm-mingw from the Longshot Builder Scene: none (game-free checks) Method: `python -I -B tests/run_all.py` from PowerShell, once on each commit; the failing checks and their unittest summaries compared How to reproduce: on Windows, `python -I -B tests/run_all.py` on main and on this branch | | Before: main @ aa95d35f | After: this PR @ dcc30ba2 | |---|---|---| | `test_cpp_preflight.py` | errors=1 | pass | | `test_make_game_prepare.py` | errors=1 | pass | | `test_missing_nup.py` | errors=8 | pass | | `test_make_game_cache.py` | failures=6, errors=14 | failures=6 (#592's); pass with #592 on top | | `test_linux_preflight.py` | failures=1, errors=17 | failures=1 (#592's); pass with #592 on top | | `test_work_lock.py` | pass | pass | | `run_all.py` in all | 541 passed, 17 failed, 35 skipped | 544 passed, 14 failed, 35 skipped | ``` main @ aa95d35f: PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: '...\longshot-missing-nup-f8t74nau\work\make_game.lock' FAIL 1.4s tests/test_make_game_cache.py FAILED (failures=6, errors=14) FAIL 3.0s tests/test_linux_preflight.py FAILED (failures=1, errors=17, skipped=1) this PR @ dcc30ba2: pass 2.9s tests/test_cpp_preflight.py pass 0.7s tests/test_make_game_prepare.py pass 0.9s tests/test_missing_nup.py pass 0.8s tests/test_work_lock.py FAIL 1.6s tests/test_make_game_cache.py FAILED (failures=6) FAIL 4.3s tests/test_linux_preflight.py FAILED (failures=1, skipped=1) this PR + #592's diff: make_game_cache => Ran 17 tests | OK linux_preflight => Ran 19 tests | OK (skipped=1) ``` ### Flags and settings None ## Testing **Tested:** `python -I -B tests/run_all.py` from PowerShell on Windows 11, on main @ aa95d35f and on this PR @ dcc30ba2 (numbers above). The 14 checks that fail here fail on main too: `test_appimage_player_build` (#624), `test_cpm_discovery` (#561), `test_crash_dialog` (#626), `test_env_on` and `test_readback_late` (#622), `test_lift_cleanup_error` (#623), `test_linux_preflight` and `test_make_game_cache` (#592), `test_oot_state_tap`, `test_options_budget_once`, `test_release` (no openssl on PATH, #144), `test_tested_configurations`, `test_vk_pgo`, `test_walk_key` (#537). `test_work_lock.py` passes, so `lock_work()` behaves as before with `release_work()` inside it. `test_make_game_cache.py` and `test_linux_preflight.py` were run again with #592's diff applied on top: both pass. **Not tested:** - Linux: there an open file doesn't stop its folder being deleted, so these checks didn't fail. The change is portable Python. I didn't run it there. - A real build: `main()` and the CLI are unchanged; the lock is still taken where it was and goes with the process. **Must be tested:** None. The game-free checks cover the change. ## Risks **What could break:** nothing for a player: no build calls `release_work()`. A check that wanted the lock held after its test finished would lose it, and none does. **Turning it off:** revert the commit. **Compatibility:** Nothing changes: saves, options, the caches, the vk ABI and the builder's behaviour are untouched. ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
test(build): the make_game checks let go of the work folder's lock, so Windows can delete their temporary folders
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Guide screenshots / Guide images and local UI source review (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 4s
Website / Website on Cloudflare (pull_request_target) Has been skipped
dcc30ba2b7
Since #630, make_game.main() takes make_game.lock in the work folder and keeps it open for the rest of the process.
Five checks run main() in their own process with the work folder in a temporary directory; on Windows the directory's
clean-up then fails with WinError 32 (the lock file is open), so test_cpp_preflight, test_make_game_prepare,
test_missing_nup, test_make_game_cache and test_linux_preflight error on main.

make_game gets release_work(), which lock_work() also uses to let go of a lock on another folder, and each of those
checks calls it before its temporary folder is removed (getattr: a source override from before #630 has none).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
d4nkn3ss changed title from WIP: test(build): the make_game checks let go of the work folder's lock, so Windows can delete their temporary folders to test(build): the make_game checks let go of the work folder's lock, so Windows can delete their temporary folders 2026-11-15 13:07:59 +00:00
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Guide screenshots / Guide images and local UI source review (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 4s
Website / Website on Cloudflare (pull_request_target) Has been skipped
This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.
Some workflows are waiting to be reviewed.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fix/test-work-lock-windows:d4nkn3ss-fix/test-work-lock-windows'
git switch 'd4nkn3ss-fix/test-work-lock-windows'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!804
No description provided.