Fix startup segfault and NVIDIA detection under WSL2 - #506
Open
zzccppp wants to merge 2 commits into
Open
Conversation
nvtop_device_get_driver() sets *driver to NULL and returns -ENOENT when the device has no driver bound. add_v3d_cards() ignored the return value and passed the result straight to strcmp(), which segfaults whenever a DRM device's parent has no bound driver. This is hit on every WSL2 system: /dev/dri/card0 is backed by the vgem platform device, which has no driver symlink in sysfs. Since every compiled-in backend enumerates all DRM devices and filters them by the parent's driver name, this NULL deref in the v3d backend crashes nvtop during gpuinfo_init_info_extraction(), before any interface is set up -- even on machines with a perfectly working NVIDIA or AMD GPU. Check the return value first, matching what the Intel backend already does in extract_gpuinfo_intel.c.
gpuinfo_nvidia_init() called dlopen("libnvidia-ml.so") first and only
fell back to "libnvidia-ml.so.1" when that dlopen itself failed. Two
problems with this:
- The unversioned libnvidia-ml.so is a development symlink, whereas the
SONAME libnvidia-ml.so.1 is the name the runtime driver installs. The
SONAME is the one that should be tried first.
- The fallback never triggered when dlopen succeeded but nvmlInit()
failed, so a loadable-but-unusable library was fatal.
Under WSL2 the two names can resolve to different files:
libnvidia-ml.so.1 finds the WSL-provided library in /usr/lib/wsl/lib
which talks to the host GPU, while the unversioned libnvidia-ml.so only
exists in the native Linux driver packages installed inside the distro,
whose nvmlInit() returns NVML_ERROR_DRIVER_NOT_LOADED because
/dev/nvidiactl is absent. nvtop consequently reported "No GPU to
monitor" on systems where nvidia-smi -- which dlopens the SONAME --
works fine.
The README already advises not to install the native driver inside WSL2,
but nvtop can simply pick the library that works instead of failing.
Move the load-symbols-and-init sequence into gpuinfo_nvidia_init_with_lib()
and try each candidate name in turn, so a failure at any step moves on to
the next one. Also record the NVML error string and dlclose the handle
when nvmlInit() fails, which previously leaked.
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.
Two independent bugs, both visible on WSL2. The first crashes nvtop at startup on any
system where a DRM device's parent has no bound driver; the second makes nvtop report
No GPU to monitoron WSL2 systems wherenvidia-smiworks fine. They are unrelated,so they are split into one commit each.
Tested on Ubuntu 24.04 under WSL2 (kernel
5.15.167.4-microsoft-standard-WSL2),RTX 4090, Windows driver 596.49, built from
3d4a953with default backend options.1. Segfault at startup when a DRM device has no driver
nvtopsegfaults before drawing anything:add_v3d_cards()discards the return value ofnvtop_device_get_driver():but that function explicitly reports failure by writing
NULLand returning-ENOENT(
src/device_discovery_linux.c:73):so
strcmp(NULL, "v3d")dereferences a null pointer.On WSL2 this triggers every time:
/dev/dri/card0is backed by thevgemplatformdevice, which has no
driversymlink in sysfs:Because every compiled-in backend enumerates all DRM devices and filters them by the
parent's driver name, and
V3D_SUPPORTdefaults toONon Linux, this null deref inthe v3d backend takes down the whole process during
gpuinfo_init_info_extraction()--including on machines whose actual GPU is a working NVIDIA or AMD card. A default
Linux build of nvtop therefore cannot start at all under WSL2.
The Intel backend already handles this correctly in
src/extract_gpuinfo_intel.c:101;this change makes the v3d backend do the same.
2.
No GPU to monitoron WSL2 while nvidia-smi worksWith the crash fixed, nvtop still found no GPU, even though
nvidia-smireported theRTX 4090 normally.
gpuinfo_nvidia_init()loaded the wrong NVML:Two problems:
libnvidia-ml.sois a development symlink, while the SONAMElibnvidia-ml.so.1is what the runtime driver installs. The SONAME should be triedfirst.
dlopen. Whendlopensucceeds butnvmlInit()fails,
gpuinfo_nvidia_init()just returns false and never tries the other name.On WSL2 the two names resolve to different files, because
/etc/ld.so.conf.d/ld.wsl.confputs
/usr/lib/wsl/libon the search path but that directory only ships the SONAME:nvmlInit_v2()libnvidia-ml.so.1/usr/lib/wsl/lib/libnvidia-ml.so.1(WSL-provided)0— success, 1 devicelibnvidia-ml.so/usr/lib/x86_64-linux-gnu/libnvidia-ml.so(native driver)9—NVML_ERROR_DRIVER_NOT_LOADEDThe native library fails because it wants
/dev/nvidiactl, which does not exist underWSL2 (
/dev/dxgis used instead).nvidia-smiworks on the same system preciselybecause it dlopens the SONAME.
I am aware the README already advises against installing the native Linux driver inside
WSL2, and that is still the right advice. But nvtop does not have to be fatally confused
by it when a usable library is present: trying candidates until one initializes is
strictly more robust, and the
dlopen-succeeded-but-nvmlInit-failed case is worthhandling on its own regardless of WSL.
This moves the load-symbols-and-init sequence into
gpuinfo_nvidia_init_with_lib()andtries each candidate in turn, so a failure at any step moves on to the next name. It
also records the NVML error string and
dlclose()s the handle whennvmlInit()fails,which previously leaked the handle and left
local_error_stringstale.Testing
Segmentation fault (core dumped).No GPU to monitor.The interactive TUI renders correctly as well (device bar, PCIe RX/TX, clocks, plots).
I do not have a Raspberry Pi to verify the v3d path still matches on real v3d hardware,
but the change only adds an error check ahead of the existing
strcmp, so a device thatpreviously compared equal to
"v3d"still does.