Repository navigation
fix(builder): Linux Play leaves the game its hookshot_log.txt again - #2279
Merged
Merged
Conversation
Since NotRexed#2024 the Builder's Play (and the launcher's, which the menu entry opens) ran the game with a pipe on stderr. The game takes a pipe for a reader (host/posix/win32_posix.c GetFileType: FILE_TYPE_PIPE) and then opens no hookshot_log.txt: a player who pressed Play had no log, only the first 64 KiB of it in hookshot_startup.log once the game had closed. Play now gives the game one end of a socket for stderr and the script reads the other. The game takes a socket for nowhere to log, as it takes the journal's under a desktop launcher, and writes its hookshot_log.txt as before NotRexed#2024; hookshot_startup.log keeps what it prints before that log opens (an SDL or loader failure) and its exit status. The test runs Play with a game that decides where to log by the shim's own GetFileType; it fails on main (no hookshot_log.txt). Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 11, 2026
Contributor
Author
|
Thanks for the careful read. About the workflows: GitHub now starts them for my pushes without an approval (it did for #2380). Main's game-free tests fail until #2380 is in, so I'll rebase this onto main right after that merge and push; the Linux AppImage, Windows builder and game-free runs should then show here on their own. |
LNDF
added a commit
to LNDF/Hookshot
that referenced
this pull request
Nov 11, 2026
Conflicts resolved: - MKWVK_API_VERSION 18: upstream's version 17 is prompts_live (NotRexed#2366); the data folder's MkwVkHost.data_dir follows it as version 18. - host/hos_update.c: "Skip this version" stays in the data folder; upstream's call order (NotRexed#2283, the check after the saves' place is known) is kept, with hos_data_init having chosen that place first. tests/test_linux_update_skip.py builds the start with hos_data.c instead of the removed saves_dir. - host/prompts.c: upstream's live prompts and mod size tables (NotRexed#2366, NotRexed#2270), with the generated files (and the new rsizetable.mod.zs) in cache/prompts; made_dir makes cache/ too. - builder/linux/play-diagnostics.sh: upstream's socket stderr (NotRexed#2279), with hookshot_startup.log in logs/. - The program cache moved to vk_progcache.cpp (NotRexed#2323): its path is cache/. - hookshot_driver_faults.txt (NotRexed#1823) goes to cache/ and is moved there. - env_on/env_value_off (NotRexed#2042), env_override (vk_menu.cpp), the prepare watchdog (vk_main.cpp), audio and docs merged with the data folder paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Since #2024, a Linux player who starts the game with Play (in the Builder after a build, or in the launcher that the Hookshot menu entry and
hookshotin the game folder open) gets no newhookshot_log.txt: the game writes its log into #2024's capture instead, which keeps the first 64 KiB inhookshot_startup.logonce the game has closed and throws the rest away. The log every issue asks for is missing, or an older run's log is still there and gets sent in its place.Fixes #2330.
Why it happened
play-diagnostics.shruns the game as"$1" 2>&1 >/dev/null | head -c 65536 ..., so the game's stderr is a pipe. The game openshookshot_log.txtonly when its stderr is nowhere to log (host/hos_main.c:GetFileType(err) == FILE_TYPE_UNKNOWN), and the POSIX shim answersFILE_TYPE_PIPEfor a pipe (host/posix/win32_posix.cGetFileType): to the game, a pipe means someone reads its output, as with./bin/hookshot | tee. Before #2024, Play gave the game/dev/null, which counts as nowhere, so it wrote its log.What changed
builder/linux/hookshot_builder.pyplay(): the game's stderr is one end of asocket.socketpair(), and the script reads the other end on its stdin. The shim counts a socket as nowhere to log (it says so for the journal's socket a desktop launcher gives), so the game writeshookshot_log.txtand keepshookshot_log.1.txtto.4.txt, as before fix(builder): retain bounded Linux Play startup diagnostics #2024.builder/linux/play-diagnostics.sh: reads the socket instead of a pipe. What reaches it is what the game prints before its log opens. On Linux the display start comes first, sodisplay: SDL_Init: ...: no windowand the loader's errors land there, along with the udmabuf warning the game already mirrors there.hookshot_startup.logkeeps that, the 64 KiB cap and the exit status, as fix(builder): retain bounded Linux Play startup diagnostics #2024 made it. The game's stdin is now/dev/nullinstead of the Builder's. If the script cannot make its temporary folder, the game gets/dev/nullfor stderr, as before fix(builder): retain bounded Linux Play startup diagnostics #2024.Hookshot.AppImage --play(hookshot-launch) never went through the script and is unchanged.Why a socket and not a change in the game (a marker that makes it log even with a launcher's pipe): every game folder would need a new build, and a folder built before the change, started from a newer Builder, would still have no log. The script also cannot know in advance whether the game will fail early, so it cannot pick between the two set-ups.
How it was tested
tests/test_linux_play_diagnostics.pykeeps fix(builder): retain bounded Linux Play startup diagnostics #2024's checks and adds one. Play starts a small game compiled with the shim's ownGetFileType(cut fromhost/posix/win32_posix.c). It prints a line, openshookshot_log.txtonly whenGetFileType(stderr)isFILE_TYPE_UNKNOWNashost/hos_main.cdoes (the test checks that this condition is still there), and logs 16,384 lines, more than 64 KiB. Onmainthe check fails (no hookshot_log.txt). With this change the whole log is inhookshot_log.txt, andhookshot_startup.logholds the first line and the exit status. It was also run with dash 0.5.12 as the shell (Debian's and Ubuntu's/bin/sh): it passes, and fails onmainthe same way.python -I -B tests/run_all.pyon this branch as opened (77a9112, onmain49f75dc): 362 passed, 2 failed, 10 skipped. The 2 failures also fail onmainon this machine, for reasons outside this change:tests/test_updater_asset_digest.py(its fixture needs the .NET 8 SDK, and only .NET 10 is installed) andtests/test_wayland_libdecor_hint.py(a clang 23 warning under-Werror).The real game: a build of
main(bdfe09c, with the same log set-up asmaintoday) on an RTX 4090 with NVIDIA 615.78.08 on Arch Linux. The folder was laid out as the Builder lays it out (bin/hookshot), and each start went through the Builder's ownplay(), imported fromhookshot_builder.pyof each revision. The runs were headless and muted, and the game was ended with SIGTERM after 30 s (as closing it would):hookshot_log.txthookshot_startup.log/dev/nullmainvk: 600 presentsreport) andHookshot exited with status 143vi: 1037 frames presented; the run before's log moved tohookshot_log.1.txtHookshot exited with status 143A start that fails before the log opens (no display reachable, so SDL's video start fails in
mainbefore the log is set up):mainand this branch leave the same 175-bytehookshot_startup.log(display: SDL_Init: wayland,x11 not available: no windowandHookshot exited with status 1), and nohookshot_log.txt. What fix(builder): retain bounded Linux Play startup diagnostics #2024 added for this case is kept.A start that fails after the log has opened: an empty
image.bin, whichplay()still starts. The game logs its first lines, then stops withimage.bin: 0 bytes, the lifted code expects 0x6020000: lift and image do not match, exit 1. Withmain's Play these three lines and the exit status are inhookshot_startup.log, and nohookshot_log.txtis written. With this change they are inhookshot_log.txt(274 bytes, the message is its last line), andhookshot_startup.logholds onlyHookshot exited with status 1.Not tested
play()the button calls.socketis part of every CPython, including the AppImage's python-build-standalone 3.12 (the version these runs used).#1958 (profiles) changes two lines of the same test file. Whichever merges second needs a small rebase there.
Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com