WIP: fix(linux): the log says why the renderer did not load #34

Draft
dyst wants to merge 1 commit from dyst/Longshot:fix/renderer-load-error into main
First-time contributor

Why

When the Linux renderer fails to load, the log says only (2), for a missing file and a longshot_vk.so from another build alike. The second needs explaining: it takes symbols from the executable, so it fails at dlopen, before mkwvk_init's version check, and the game quietly falls back to WebGPU.

What changed

  • host: LoadLibraryA in host/posix/win32_posix.c keeps dlerror()'s text for the last failure, per thread (load_error, cleared at the start of each call), and hos_load_error() returns it ("" after a success). GetLastError() is still ERROR_FILE_NOT_FOUND, as before. host/posix/windows.h declares hos_load_error.

  • host: load_vulkan in host/rx_backend.c prints that text in its failure line on Linux:

    rx: RX_BACKEND=vulkan, but .../longshot_vk.so did not load (.../longshot_vk.so: undefined symbol: mkwvk_...): WebGPU
    

    Windows keeps the error number, which already tells a missing file (126) from a missing function (127).

  • tests: tests/test_renderer_load_error.py (new): everywhere, the source keeps the text and logs it (it fails on main); on Linux, it builds win32_posix.c as it is and loads, through LoadLibraryA, a .dll name with no library behind it, a library that needs a symbol nothing has, then a good one.

Flags and settings

None.

Measurements

Nothing to measure in the game: the change is the failure path's log line on Linux. What was run, on the GitHub version (NotRexed/Hookshot#2875):

  • The new check's Linux part, by hand on WSL Ubuntu (gcc), as the check does it:

    failed|2|<tmp>/absent_vk.so: cannot open shared object file: No such file or directory
    failed|2|<tmp>/needs.so: undefined symbol: mkwvk_from_another_build
    loaded|0|
    
  • Every check that reads the changed files (37), through run_all.py, rebased on GitHub's main of that day, on Windows: 34 pass; nx2/test_bc_storage_views.py, nx2/test_dll.py and nx2/test_leaf.py fail the same way on main there. The new check's Linux part is skipped on Windows.

Testing

Tested: the runs under Measurements (on the GitHub version) and the game-free checks this description names. Checked but not measured: the Linux part of the new check, on WSL Ubuntu (gcc).

Not tested: the game on Linux. The loader message runs in the game, and was exercised outside it (WSL) only.

Needs other testers:

  • Linux: a renderer that fails to load (a missing symbol), expecting longshot_log.txt to name the reason (request to open)

Screenshots

Nothing on screen.

Risk and rollback

Only the Linux failure path's log line changes: a successful load and Windows are as before, and GetLastError() still says ERROR_FILE_NOT_FOUND. The text is cut to 512 bytes in a per-thread buffer. Reverting the commit is enough.

Reviewer notes

Carried over from NotRexed/Hookshot#2875 with the move to Longshot: the same change on Longshot's main, with its rename applied. Its review and discussion are there.

A draft: its Linux loader message runs in the game, and was exercised outside it (WSL) only.

The checks were done on the GitHub version; this branch is the same change with the rename applied (the same files and line counts). Forgejo runs no checks; they were not run again here. Only the checks that read the changed files were run, not the whole suite. Part of the dev-loop proposal's B1 (NotRexed/Hookshot#2636): a renderer swap during development needs this line to say why the new one was refused.

Issues

None on Longshot. See NotRexed/Hookshot#2636 (B1).

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Testing.
  • Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests).
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported.
  • 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.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Flags table filled in; README / docs/development.md switch reference updated.
  • Screenshots for a change that shows on screen.
  • A row in docs/tested-configurations.md for each measured run.
  • MKWVK_API_VERSION bumped (gpu/vk/vk_api.h's MkwVkHost or MkwVkRenderer changed).
  • The SPIR-V headers regenerated with glslang (a shader changed).
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths.
  • Docs updated.

🤖 Generated with Claude Code

## Why When the Linux renderer fails to load, the log says only `(2)`, for a missing file and a `longshot_vk.so` from another build alike. The second needs explaining: it takes symbols from the executable, so it fails at `dlopen`, before `mkwvk_init`'s version check, and the game quietly falls back to WebGPU. ## What changed - host: `LoadLibraryA` in `host/posix/win32_posix.c` keeps `dlerror()`'s text for the last failure, per thread (`load_error`, cleared at the start of each call), and `hos_load_error()` returns it (`""` after a success). `GetLastError()` is still `ERROR_FILE_NOT_FOUND`, as before. `host/posix/windows.h` declares `hos_load_error`. - host: `load_vulkan` in `host/rx_backend.c` prints that text in its failure line on Linux: ``` rx: RX_BACKEND=vulkan, but .../longshot_vk.so did not load (.../longshot_vk.so: undefined symbol: mkwvk_...): WebGPU ``` Windows keeps the error number, which already tells a missing file (126) from a missing function (127). - tests: `tests/test_renderer_load_error.py` (new): everywhere, the source keeps the text and logs it (it fails on `main`); on Linux, it builds `win32_posix.c` as it is and loads, through `LoadLibraryA`, a `.dll` name with no library behind it, a library that needs a symbol nothing has, then a good one. ## Flags and settings None. ## Measurements Nothing to measure in the game: the change is the failure path's log line on Linux. What was run, on the GitHub version (NotRexed/Hookshot#2875): - The new check's Linux part, by hand on WSL Ubuntu (gcc), as the check does it: ``` failed|2|<tmp>/absent_vk.so: cannot open shared object file: No such file or directory failed|2|<tmp>/needs.so: undefined symbol: mkwvk_from_another_build loaded|0| ``` - Every check that reads the changed files (37), through `run_all.py`, rebased on GitHub's `main` of that day, on Windows: 34 pass; `nx2/test_bc_storage_views.py`, `nx2/test_dll.py` and `nx2/test_leaf.py` fail the same way on `main` there. The new check's Linux part is skipped on Windows. ## Testing **Tested:** the runs under Measurements (on the GitHub version) and the game-free checks this description names. Checked but not measured: the Linux part of the new check, on WSL Ubuntu (gcc). **Not tested:** the game on Linux. The loader message runs in the game, and was exercised outside it (WSL) only. **Needs other testers:** - Linux: a renderer that fails to load (a missing symbol), expecting longshot_log.txt to name the reason (request to open) ## Screenshots Nothing on screen. ## Risk and rollback Only the Linux failure path's log line changes: a successful load and Windows are as before, and `GetLastError()` still says `ERROR_FILE_NOT_FOUND`. The text is cut to 512 bytes in a per-thread buffer. Reverting the commit is enough. ## Reviewer notes Carried over from [NotRexed/Hookshot#2875](https://github.com/NotRexed/Hookshot/pull/2875) with the move to Longshot: the same change on Longshot's `main`, with its rename applied. Its review and discussion are there. A draft: its Linux loader message runs in the game, and was exercised outside it (WSL) only. The checks were done on the GitHub version; this branch is the same change with the rename applied (the same files and line counts). Forgejo runs no checks; they were not run again here. Only the checks that read the changed files were run, not the whole suite. Part of the dev-loop proposal's B1 ([NotRexed/Hookshot#2636](https://github.com/NotRexed/Hookshot/pull/2636)): a renderer swap during development needs this line to say why the new one was refused. ## Issues None on Longshot. See [NotRexed/Hookshot#2636](https://github.com/NotRexed/Hookshot/pull/2636) (B1). ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [ ] Rebased on current `main`. - [ ] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Testing. - [x] Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests). - [ ] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. - [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. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [ ] Flags table filled in; README / docs/development.md switch reference updated. - [ ] Screenshots for a change that shows on screen. - [ ] A row in `docs/tested-configurations.md` for each measured run. - [ ] `MKWVK_API_VERSION` bumped (`gpu/vk/vk_api.h`'s `MkwVkHost` or `MkwVkRenderer` changed). - [ ] The SPIR-V headers regenerated with glslang (a shader changed). - [x] A game-free test added for the fix, failing on `main` and passing here. - [ ] A check under `tests/` that reads changed source updated in this PR, not weakened. - [ ] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. - [ ] Docs updated. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
longshot_vk.so is opened with RTLD_NOW and takes symbols from the
executable, so one from another build fails at dlopen, before
mkwvk_init's version check, and the game falls back to WebGPU. The POSIX
LoadLibraryA kept only ERROR_FILE_NOT_FOUND, so the log said "(2)" for
that and for a missing file alike. It keeps dlerror()'s text
(hos_load_error), and load_vulkan prints it:

  rx: RX_BACKEND=vulkan, but .../longshot_vk.so did not load
  (.../longshot_vk.so: undefined symbol: mkwvk_...): WebGPU

tests/test_renderer_load_error.py: the source everywhere; on Linux,
the shim as it is loading a missing file, a library needing a missing
symbol and a good one. Part of the dev-loop proposal's B1 (#2636).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Author
First-time contributor

Back to WIP under #48's process: this was carried over before the new template. Its description will be brought to the template and measured on Longshot (main against this PR, at named commits) when it's wanted for review; ask here if you'd like it sooner.

Back to WIP under #48's process: this was carried over before the new template. Its description will be brought to the template and measured on Longshot (main against this PR, at named commits) when it's wanted for review; ask here if you'd like it sooner.
Author
First-time contributor

Description brought to Longshot's PR template (#48). Still WIP: its numbers are from the GitHub version, and it isn't rebased on current main; it gets measured on Longshot (main against this PR, at named commits) before it is marked ready.

Description brought to Longshot's PR template (#48). Still WIP: its numbers are from the GitHub version, and it isn't rebased on current main; it gets measured on Longshot (main against this PR, at named commits) before it is marked ready.
Author
First-time contributor

Description moved to the template's Testing section and whole checklist (#72): what was tested, what wasn't, and what needs other testers (their test requests to open while this is WIP).

Description moved to the template's Testing section and whole checklist (#72): what was tested, what wasn't, and what needs other testers (their test requests to open while this is WIP).
This pull request is marked as a work in progress.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fix/renderer-load-error:dyst-fix/renderer-load-error'
git switch 'dyst-fix/renderer-load-error'
Sign in to join this conversation.
No description provided.