From bf40c53e1eec35198b85fe2c323a1e8e96b90554 Mon Sep 17 00:00:00 2001 From: arcattack Date: Sat, 25 Jul 2026 18:37:56 -0500 Subject: [PATCH] Launchers: make the handoff wait tool-independent -- my first version broke on any PATH carrying Git-Bash/MSYS Regression in my own fix from an hour ago, reported immediately by the operator on relaunch: find: '/I': No such file or directory find: 'btl4.exe': No such file or directory The game has exited. ... The wait loop called bare `find`, which resolves to the MSYS/Git-Bash **Unix** find on any box with git on PATH (confirmed here: `which find` -> /usr/bin/find, `which timeout` -> /usr/bin/timeout). So the loop errored out and fell straight through -- restoring exactly the misleading "The game has exited" message it was meant to remove. `timeout` was the same exposure one line later (GNU coreutils ships one, with different arguments), so the block had TWO PATH-dependent failures. Harmless to the game (the loop only reports; it never touched the session), but it made the fix a no-op for anyone with git installed -- which is every developer and a fair number of players. FIX: no external tools at all. * detection is now a pure-cmd `for /f "tokens=1"` over tasklist output, comparing the first token to btl4.exe -- no find/findstr; * tasklist and timeout are both invoked by ABSOLUTE %SystemRoot%\System32 path, so a shadowing PATH cannot reach them. Failure modes stay safe: if tasklist is unavailable the variable never gets set and the loop degrades to reporting immediately (the old behaviour, never a hang), and a genuinely dead exe still falls straight through so the #41 launch forensics are untouched. VERIFIED both branches by running the shipped detection lines from THIS bash shell -- i.e. the hostile shadowed PATH that broke v1, a harder case than a playtester's clean environment: game running -> RESULT: WOULD-WAIT [process detected] absent-name control -> RESULT: WOULD-EXIT [no process] No find/timeout errors in either. (players/ is the shipped source per tools/mkdist.py:78; the gitignored root copies re-synced byte-identical.) Co-Authored-By: Claude Opus 5 (1M context) --- players/join.bat | 20 ++++++++++++++++---- players/join_lan.bat | 20 ++++++++++++++++---- players/play_solo.bat | 20 ++++++++++++++++---- players/play_steam.bat | 20 ++++++++++++++++---- 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/players/join.bat b/players/join.bat index 8129612..ff9f42f 100644 --- a/players/join.bat +++ b/players/join.bat @@ -37,13 +37,25 @@ rem (btl4console.cpp). So OUR child exiting means "the menu handed off", rem NOT "the game closed" -- without this wait the window announced "The rem game has exited" while the game was still loading, which reads as a rem crash to a playtester. Wait for the handed-off generation(s) to go. +rem +rem NO EXTERNAL TOOLS: `find`, `findstr` and `timeout` are all shadowed by +rem Git-Bash / MSYS / GnuWin32 builds of the same names when those are on +rem PATH (a dev box, or a player who installed git). The MSYS `find` is +rem the Unix one and dies with "find: '/I': No such file or directory", +rem and GNU `timeout` takes different arguments. So: parse tasklist with +rem a pure-cmd for/f, and call both helpers by ABSOLUTE System32 path. rem A genuinely dead exe leaves no process and falls straight through, so -rem the #41 launch forensics above still work. +rem the #41 launch forensics above still work. If tasklist is missing +rem entirely the loop degrades to reporting immediately -- the old +rem behaviour, never a hang. rem ------------------------------------------------------------------ :btwait -tasklist /FI "IMAGENAME eq btl4.exe" /NH 2>nul | find /I "btl4.exe" >nul -if not errorlevel 1 ( - timeout /t 2 /nobreak >nul +set "BT_STILL_RUNNING=" +for /f "tokens=1" %%P in ('%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq btl4.exe" /NH 2^>nul') do ( + if /I "%%P"=="btl4.exe" set "BT_STILL_RUNNING=1" +) +if defined BT_STILL_RUNNING ( + %SystemRoot%\System32\timeout.exe /t 2 /nobreak >nul 2>nul goto btwait ) echo. diff --git a/players/join_lan.bat b/players/join_lan.bat index 7d36037..185d1c3 100644 --- a/players/join_lan.bat +++ b/players/join_lan.bat @@ -40,13 +40,25 @@ rem (btl4console.cpp). So OUR child exiting means "the menu handed off", rem NOT "the game closed" -- without this wait the window announced "The rem game has exited" while the game was still loading, which reads as a rem crash to a playtester. Wait for the handed-off generation(s) to go. +rem +rem NO EXTERNAL TOOLS: `find`, `findstr` and `timeout` are all shadowed by +rem Git-Bash / MSYS / GnuWin32 builds of the same names when those are on +rem PATH (a dev box, or a player who installed git). The MSYS `find` is +rem the Unix one and dies with "find: '/I': No such file or directory", +rem and GNU `timeout` takes different arguments. So: parse tasklist with +rem a pure-cmd for/f, and call both helpers by ABSOLUTE System32 path. rem A genuinely dead exe leaves no process and falls straight through, so -rem the #41 launch forensics above still work. +rem the #41 launch forensics above still work. If tasklist is missing +rem entirely the loop degrades to reporting immediately -- the old +rem behaviour, never a hang. rem ------------------------------------------------------------------ :btwait -tasklist /FI "IMAGENAME eq btl4.exe" /NH 2>nul | find /I "btl4.exe" >nul -if not errorlevel 1 ( - timeout /t 2 /nobreak >nul +set "BT_STILL_RUNNING=" +for /f "tokens=1" %%P in ('%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq btl4.exe" /NH 2^>nul') do ( + if /I "%%P"=="btl4.exe" set "BT_STILL_RUNNING=1" +) +if defined BT_STILL_RUNNING ( + %SystemRoot%\System32\timeout.exe /t 2 /nobreak >nul 2>nul goto btwait ) echo. diff --git a/players/play_solo.bat b/players/play_solo.bat index 57fda3d..a7edf1e 100644 --- a/players/play_solo.bat +++ b/players/play_solo.bat @@ -36,13 +36,25 @@ rem (btl4console.cpp). So OUR child exiting means "the menu handed off", rem NOT "the game closed" -- without this wait the window announced "The rem game has exited" while the game was still loading, which reads as a rem crash to a playtester. Wait for the handed-off generation(s) to go. +rem +rem NO EXTERNAL TOOLS: `find`, `findstr` and `timeout` are all shadowed by +rem Git-Bash / MSYS / GnuWin32 builds of the same names when those are on +rem PATH (a dev box, or a player who installed git). The MSYS `find` is +rem the Unix one and dies with "find: '/I': No such file or directory", +rem and GNU `timeout` takes different arguments. So: parse tasklist with +rem a pure-cmd for/f, and call both helpers by ABSOLUTE System32 path. rem A genuinely dead exe leaves no process and falls straight through, so -rem the #41 launch forensics above still work. +rem the #41 launch forensics above still work. If tasklist is missing +rem entirely the loop degrades to reporting immediately -- the old +rem behaviour, never a hang. rem ------------------------------------------------------------------ :btwait -tasklist /FI "IMAGENAME eq btl4.exe" /NH 2>nul | find /I "btl4.exe" >nul -if not errorlevel 1 ( - timeout /t 2 /nobreak >nul +set "BT_STILL_RUNNING=" +for /f "tokens=1" %%P in ('%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq btl4.exe" /NH 2^>nul') do ( + if /I "%%P"=="btl4.exe" set "BT_STILL_RUNNING=1" +) +if defined BT_STILL_RUNNING ( + %SystemRoot%\System32\timeout.exe /t 2 /nobreak >nul 2>nul goto btwait ) echo. diff --git a/players/play_steam.bat b/players/play_steam.bat index 9898125..19284dc 100644 --- a/players/play_steam.bat +++ b/players/play_steam.bat @@ -30,13 +30,25 @@ rem (btl4console.cpp). So OUR child exiting means "the menu handed off", rem NOT "the game closed" -- without this wait the window announced "The rem game has exited" while the game was still loading, which reads as a rem crash to a playtester. Wait for the handed-off generation(s) to go. +rem +rem NO EXTERNAL TOOLS: `find`, `findstr` and `timeout` are all shadowed by +rem Git-Bash / MSYS / GnuWin32 builds of the same names when those are on +rem PATH (a dev box, or a player who installed git). The MSYS `find` is +rem the Unix one and dies with "find: '/I': No such file or directory", +rem and GNU `timeout` takes different arguments. So: parse tasklist with +rem a pure-cmd for/f, and call both helpers by ABSOLUTE System32 path. rem A genuinely dead exe leaves no process and falls straight through, so -rem the #41 launch forensics above still work. +rem the #41 launch forensics above still work. If tasklist is missing +rem entirely the loop degrades to reporting immediately -- the old +rem behaviour, never a hang. rem ------------------------------------------------------------------ :btwait -tasklist /FI "IMAGENAME eq btl4.exe" /NH 2>nul | find /I "btl4.exe" >nul -if not errorlevel 1 ( - timeout /t 2 /nobreak >nul +set "BT_STILL_RUNNING=" +for /f "tokens=1" %%P in ('%SystemRoot%\System32\tasklist.exe /FI "IMAGENAME eq btl4.exe" /NH 2^>nul') do ( + if /I "%%P"=="btl4.exe" set "BT_STILL_RUNNING=1" +) +if defined BT_STILL_RUNNING ( + %SystemRoot%\System32\timeout.exe /t 2 /nobreak >nul 2>nul goto btwait ) echo.