test: the recorder exit check catches the old destructor on llvm-mingw too #2240
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!2240
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/recorder-exit-sentinel-order"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
tests/test_recorder_sync.pyfails on Windows with llvm-mingw: its exit check's negative control (the old recorder destructor) passes there, so the runner reports "FAIL: the exit test passes the old destructor" (reported by Arkex-ai on #1473). The control was not discriminating on that toolchain; nothing in the game changed.Cause
The fixture's sentinel must be destroyed after the recorder's global so that its line proves every DLL destructor ran. The recorder's global (
g_rec) is an inline variable, and inline variables' dynamic initialization is only partially ordered against a file's own statics. With llvm-mingw 20261104,g_recwas made first, so the sentinel printed its line before the old destructor ended the process.Static linking (as
hookshot_vk.dlllinks) made no difference; a minimal DLL with a mutex held by a thread killed atExitProcessshows llvm-mingw's libc++ ending the process when a destructor takes that mutex, as the fixture expects.Change
tests/recorder_exit_test.cpp: the sentinel gets__attribute__((init_priority(101))), so it is constructed first and destroyed last on every compiler that builds the test. The header comment now says which runtimes hang and which end the process.Tested
Windows 11,
python -I -X utf8 -B tests/test_recorder_sync.py --cxx <cxx> --headers <Vulkan-Headers/include>:Before the change, llvm-mingw reproduced the reported failure (NOT CAUGHT, exit code 0 with the sentinel line).
Not covered
Only the test fixture changes; Linux skips this check (Windows-only, as before).
🤖 Generated with Claude Code
Looks good. The diagnosis fits: an inline variable's dynamic init is only partially ordered against the file's own statics, so llvm-mingw could build g_rec first and the sentinel then printed before the old destructor killed the process. init_priority(101) makes the sentinel first-constructed/last-destroyed, which is what the comment already promised, and 101 is outside the reserved 0-100 range. It is a plain attribute that clang (both targets) and GCC accept, so no portability issue, and the change is test-only with no timing or thread logic added (the 20 s watchdog and the negative control in tests/test_recorder_sync.py are untouched).
The test is still declared via RUN_ALL_ARGS in test_recorder_sync.py, and the exit check still skips off Windows, so Linux is unaffected. CI is green on Linux and Windows (windows-2022 source checks, llvm-mingw Vulkan back end). The four-compiler table in the description (pass on current code, old destructor caught) covers the real fix; I did not run it myself.
Nit: the sentinel's comment now explains the ordering well; no change needed.