Skip to content

fix(gui): restart the tray for a new NVIDIA driver instead of crashing - #73

Open
Rovey wants to merge 1 commit into
mainfrom
fix/driver-update-restart
Open

Rovey wants to merge 1 commit into
mainfrom
fix/driver-update-restart

Conversation

@Rovey

@Rovey Rovey commented Nov 5, 2026

Copy link
Copy Markdown
Owner

Why

On 2026-11-05 the tray (0.4.8-rc8, the same code as 0.4.8 here) crashed while the NVIDIA driver 617.14 was replaced by 621.14:

GpuAutoOptimizer.exe  Exception code: 0xc0000409  Faulting module: unknown  (20:58:03)

The card was left at stock and the user heard nothing until the next logon. A driver update every few weeks makes this the case most users meet.

The crash dump (%LOCALAPPDATA%\CrashDumps, read with a small minidump parser):

  • the exception is a fast fail with code 10, FAST_FAIL_GUARD_ICALL_CHECK_FAILURE: Control Flow Guard stopped an indirect call to an address that is no valid target, here one in no loaded module;
  • the faulting stack runs GpuAutoOptimizer.exe -> nvml.dll from nv_dispi.inf_amd64_da865124... (the old driver, 2026-10-02) -> ntdll;
  • loaded at the same time: nvapi64_impl.dll from nv_dispi.inf_amd64_cee48bd6... (the new driver, 20:57:32); the old nvapi64.dll and nvapi64_impl.dll are in the unloaded-module list.

So the tray had lost the device, started its libraries again (hw_lost / retry_hw), got NVAPI from the new driver but NVML's implementation from the old one, and that NVML called into code that was gone. Nothing in the process can make NVML fresh again.

What

  • gao::compare_driver_files (core, pure): Same, Changed or Unknown for the stamp (write time, size) of System32\nvml.dll against the one taken when the process first loaded the libraries.
  • gao::nvml_library_stamp() (hw): that stamp, read with GetFileAttributesExW, without loading anything.
  • Tray: the stamp is taken before init_hw() and compared every second in on_telemetry. A change stops every call into the loaded libraries (hw_lost); retry_hw then never reconnects to them but calls restart_for_new_driver():
    • during a run, or while a run's result is on the screen: waits, and says so once in boot.log;
    • an elevated copy outside Program Files: closes itself with a boot.log line (as after a fault, fix: review findings before 0.4.9 #67);
    • otherwise starts a new copy with --resume --driver-updated (and --hidden when the window was closed).
  • The new copy retries the libraries until the new driver answers, and then shows the same balloon as the logon apply after an update ("Click here and test it (5 minutes)").
  • While the file is missing mid-install (Unknown) nothing is called and nothing restarts.

Tests

  • cmake --workflow --preset ci: builds with /W4 /WX; core_tests and app_tests pass. New unit test for compare_driver_files.
  • Not yet on the card. The hardware check: install this build, start a driver (re)install with the tray running, then read boot.log (restarting the app to load its libraries), the Application log (no crash) and see the balloon.

🤖 Generated with Claude Code

The tray crashed with 0xc0000409 while driver 617.14 was replaced by
621.14. Its dump: Control Flow Guard fast fail 10 inside nvml.dll, with
NVML's implementation from the old driver's folder still loaded after the
libraries were started again, next to NVAPI's from the new one. The card
was left at stock without a word until the next logon.

The tray now stamps System32\nvml.dll when it loads the libraries and
looks at it every second. A new stamp stops all calls into the loaded
libraries; the app then starts a new copy of itself (not during a run, and
an elevated copy only from Program Files), which loads the new driver's
libraries, waits until they answer and shows the balloon that asks for the
5-minute retest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant