NVML device handle cached at discovery → native access violation (0xc0000005) when the GPU is restarted

Open
#2,523 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
68/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
csharp

Research direction

Read Hardware/Gpu/NvidiaGpu.cs to trace how the NVML handle is acquired and used during Update(), then compare the handle re-acquisition pattern in Hardware/Battery/Battery.cs and commit 9e54127. Reproduce the restart-device scenario with pnputil and verify that polling skips unavailable NVML sensors and resumes without a native access violation.

Written by the indexing model from the issue text.

Description

Stale NVML device handle causes access violation when NVIDIA GPU is restarted or removed

Description

NvidiaGpu acquires its NVML device handle once during construction and stores it in _nvmlDevice. Update() subsequently passes this cached handle to NvidiaML.NvmlDeviceGetPowerUsage.

If the NVIDIA GPU is restarted or removed while LibreHardwareMonitor is polling it (for example, via pnputil /restart-device or during hybrid/eject transitions), the cached handle can become stale. The subsequent native call may then fault inside nvml.dll.

This results in an uncatchable access violation that terminates the host process. The try/catch inside NvidiaML.NvmlDeviceGetPowerUsage cannot intercept the native fault.

Environment

  • Windows 11
  • .NET 9
  • LibreHardwareMonitorLib (net9.0)
  • NVIDIA dGPU

Steps to Reproduce

  1. Start LibreHardwareMonitor, or another host that polls LibreHardwareMonitor at approximately 1-second intervals.

  2. Restart the NVIDIA GPU using:

    pnputil /restart-device "<gpuInstanceId>"
    
  3. Observe the process during the device removal/reinitialization window.

Expected Behavior

Sensor updates are skipped while the NVIDIA device is temporarily unavailable, and polling resumes once the device becomes available again.

Actual Behavior

The host process terminates due to an access violation in the NVML native call.

Evidence

Application Error:

Faulting module: coreclr.dll
Exception code: 0xc0000005

.NET Runtime:

The process was terminated due to an unhandled exception.

Relevant stack:

at LibreHardwareMonitor.Interop.NvidiaML.NvmlDeviceGetPowerUsage(NvmlDevice)
at LibreHardwareMonitor.Hardware.Gpu.NvidiaGpu.Update()

Root Cause

In Hardware/Gpu/NvidiaGpu.cs, _nvmlDevice is assigned once in the constructor using an NVML device lookup such as:

  • NvmlDeviceGetHandleByPciBusId
  • NvmlDeviceGetHandleByIndex

The cached handle is then used by Update() without revalidation.

When the GPU is restarted or temporarily removed, the previously acquired NVML handle may no longer be valid. Although NVML can return a failure NvmlReturn when a device is currently absent, passing a stale handle can instead cause the native code to fault before a return value is produced.

Therefore, the exception cannot reliably be handled by the managed try/catch surrounding the NVML call.

Suggested Fix

Re-acquire the NVML device handle immediately before using it rather than relying on the handle acquired during construction.

The device's PCI bus ID can be captured during construction and used to re-acquire the handle before each update, with adapter index as a fallback if necessary.

If re-acquisition fails or returns null, skip the NVML-dependent sensors for that update instead of calling NVML with the stale handle.

A short-term mitigation could also invalidate _nvmlDevice during Close().

This would make a temporarily missing GPU result in a clean no-op rather than a stale-handle native access violation.

The approach mirrors the existing handle re-acquisition pattern in:

Hardware/Battery/Battery.cs

See commit 9e54127.

Dominant language
C#
Stars
9.1k
Forks
1k
Avg merge
1d 4h
Merged PRs (30d)
15

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from LibreHardwareMonitor/LibreHardwareMonitor

All issues in LibreHardwareMonitor/LibreHardwareMonitor

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.