Repository navigation
The controller applet's stand-in runs on the big host stack: Drag x Drive opened it from a game thread with too little stack for its log lines (SIGBUS in fprintf under focus_sync) - #1943
Conversation
…rive opened it from a game thread with too little stack for its log lines (SIGBUS in fprintf under focus_sync) Both ShowControllerSupport overloads register through HLE_FORCE_BIG, as the file system hooks do (memory.md, Host calls on small guest stacks). t_hid links hle_bigstack.c with a guest-address-space stub, as t_fs does.
… controller applet's stand-in runs there: Drag x Drive (040041601D83A000, v196608) opened the controller applet from a game thread with too little stack left for the stand-in's log lines, SIGBUS in fprintf under focus_sync / h_hid_ShowCtrl 0x60 bytes below sp, then a hang in the crash handler (the PR author's report). Formatting one line takes about 2.7 KB of stack (fprintf to stderr, measured on macOS 27.2) and a hook runs on the stack of the game thread that calls it, so every hook that logs was exposed, as the file system, add-on content and audio hooks were before they moved one by one. LOG is now one call, dm_log (dm.h): the host's definition (hle_bigstack.c) formats the line through dm_bigstack_enter, on the host stack when the caller is on a guest stack and directly anywhere else, the variable arguments read from where the caller left them; programs that do not link hle_bigstack.c (unit tests) get dm.h's weak definition, which writes on the caller's stack. A hook needs HLE_FORCE_BIG only for its own stack use: both ShowControllerSupport overloads take it (the PR's change), since with too few players the front end's prompt runs on the game's thread. t_hid and t_hid_tsan link hle_bigstack.c (the PR left t_hid_tsan out, which no longer linked), and t_audio_stats captures dm_log where it captured fprintf. Not covered: direct fprintf(stderr) calls in a hook (the thread dumps of hle_thread.c, a debug line of hle_svc.c). Checked: t_bigstack (new case: a hook logs with 1 KB of guest stack left; SIGBUS with the line written on the guest stack), make run in dm/host/tests and dm/gfx/tests, the tsan, tsan-threads and memory-tsan targets, test_docs. OCTOPATH TRAVELER II on the Mac (M4 Pro), one full regress route on this host: 59.8 fps, no red line, clean exit (main: 59.5 fps); the regress comparison itself was not completed (the window was covered, and other jobs ran). Not run: Drag x Drive (no files here), iOS (PR #1943) Co-authored-by: FifteenPen <354289956+FifteenPen@users.noreply.github.com>
|
Landed on main as 2d3fb83, in a wider form, with you credited as co-author. Thank you for the report and the diagnosis: the backtrace and the fault address 0x60 below sp were exactly what was needed. What changed against this PR:
Not run here: Drag x Drive (no files of it on this Mac). Could you retest on main, through the screen after a time trial, and say whether the crash is gone? A log from a session where the controller applet opens ( |
…ost's are: MLOG (nvn_mtl.m) wrote with fprintf directly, about 2.7 KB of stack a line, and the nvnCommandBuffer* recording calls run on the game thread's stack (every other NVN function goes through nvn_big_entry), so a line logged from one on a thread with little stack left would fault as the controller applet's did (2d3fb83). MLOG is now dm_log, as LOG is. No recording call was found to log on a small stack: this closes an exposure, not a reproduced crash. The reference entry (Log lines on small guest stacks) is corrected: the direct writes it named as not covered run on host stacks (an SVC, so the OutputDebugString line, on the thread's gate stack, entry.S; the crash handler and its thread dumps on its alternate stack; probes, haptics and save sync on host threads or behind HLE_FORCE_BIG). Open: dm_backtrace writes directly and nn::diag's abort hooks call it on the game's stack, so an abort on a thread with little stack left can fault before its backtrace. Checked: the Mac host builds without a format warning, make run in dm/gfx/tests (the graphics layer without hle_bigstack.c, so dm.h's weak definition), test_docs. Not run: a game, regress.py, iOS (PR #1943)
|
I will do that test in an hour! |
|
Waiting for shaders to build now. |
|
Retested on main be23843 (with #1944's profile on top): Drag x Drive (
Log, the session through the time trial (the applet, Home-protection and exit lines) |
What and why
Drag x Drive (
040041601D83A000, v196608, SDK 20) opened the controller applet (nn::hid::ShowControllerSupport) from one of its game threads and the host crashed in the stand-in's own log line, then hung in the crash handler at 100% CPU. This happens after completing a time trial, when the game opens the screen to show the result/offer to retry/offer to return the user to the main menu:The fault is 0x60 bytes below sp: the case of Host calls on small guest stacks. Host hooks run on the calling guest thread's stack, and the controller applet's stand-in logs twice before it answers (
DM_APPLET'soe library appletline, thenfocus_sync's focus state).fprintfneeds more than the game's thread had left.The change registers both
ShowControllerSupportoverloads throughHLE_FORCE_BIG, as the file system hooks are, so the stand-in runs on the per-thread host stack.t_hidnow linkshle_bigstack.cwith the same guest-address-space stubt_fsuses (every test stack is a host stack, so the take-over runs on it directly).The other applet stand-ins (
DM_APPLET: error, shop, Mii editor, strap guide, user selector, software keyboard) log the same way and have the same exposure on a small stack; only the controller applet was seen to overflow, so only it is moved here.Docs: the reference entry Host calls on small guest stacks gains this case (symptom, cause, fix, found on), and the symptom index its line.
Checked
make -C dm/host/tests GAME=010015100B514000 run: passes (t_hidincluded).python3 -m unittest dm/tools/tests/test_docs.py dm/tools/tests/test_env_switches.py,python3 dm/tools/docs_symptoms.py.dm/tools/lint_c.py tidy(LLVM 23.1.4) ondm/host/hle_hid.c: 0 file/check pairs above the baseline.040041601D83A000, v196608), a Mac app of main e82888e with nn::hid::EnableUnintendedHomeButtonInputProtection is answered by the host and logged: Drag x Drive no longer crashes at sdk+0x63ce10 as player 1's Joy-Con 2 joins #1921 and NVN: account for four-byte direct indexed draws using control memory #1609 (the game needs both to reach play), a pair of Joy-Con 2s, docked:regress.py: host only,hle_hid.c's two applet take-overs; they bind only where a game importsShowControllerSupport, and run the same code on another stack.regress.py checkwas not run.Docs
docs/reference/<subsystem>.mdentry, andpython3 dm/tools/docs_symptoms.pywas run (the symptom index)