From 12a3f6a0072e3a5543f178777d04838de02a7e7d Mon Sep 17 00:00:00 2001 From: Olivier Booklage Date: Sat, 16 May 2026 14:45:54 +0200 Subject: [PATCH 1/2] Pre-load NVIDIA shared libraries on Linux Mirrors the Windows preload block from #1775. When onnxruntime-gpu is installed via pip with nvidia-cudnn-cu12, the .so files sit under venv/lib/pythonX.Y/site-packages/nvidia//lib/ and the dynamic linker never sees them. LD_LIBRARY_PATH cannot be set after Python starts. Pre-loads every lib*.so* via ctypes.CDLL with RTLD_GLOBAL before onnxruntime opens its CUDA provider. Also extends LD_LIBRARY_PATH so child processes (ffmpeg) inherit the path. Fixes "libcudnn.so.9: cannot open shared object file" on pip-only Linux installs. --- run.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/run.py b/run.py index b7927df..03a6289 100644 --- a/run.py +++ b/run.py @@ -31,6 +31,38 @@ if sys.platform == "win32": except (OSError, AttributeError): pass +# On Linux, pre-load NVIDIA shared libraries (cuDNN, cuBLAS, nvrtc...) shipped +# inside the venv via pip wheels (nvidia-cudnn-cu12, etc.). LD_LIBRARY_PATH +# cannot be set after Python starts, so we use ctypes.CDLL with RTLD_GLOBAL +# instead. This makes symbols available to onnxruntime when it dlopens its +# CUDA provider. +if sys.platform.startswith("linux"): + import ctypes + import glob + _py_lib = f"python{sys.version_info.major}.{sys.version_info.minor}" + _site_packages_candidates = [ + os.path.join(project_root, "venv", "lib", _py_lib, "site-packages"), + os.path.join(sys.prefix, "lib", _py_lib, "site-packages"), + ] + for _sp in _site_packages_candidates: + _nvidia_dir = os.path.join(_sp, "nvidia") + if not os.path.isdir(_nvidia_dir): + continue + for _pkg in os.listdir(_nvidia_dir): + _lib_dir = os.path.join(_nvidia_dir, _pkg, "lib") + if not os.path.isdir(_lib_dir): + continue + # Also expose the directory to child processes + os.environ["LD_LIBRARY_PATH"] = ( + _lib_dir + os.pathsep + os.environ.get("LD_LIBRARY_PATH", "") + ) + for _so in sorted(glob.glob(os.path.join(_lib_dir, "lib*.so*"))): + try: + ctypes.CDLL(_so, mode=ctypes.RTLD_GLOBAL) + except OSError: + pass + break + from modules import platform_info platform_info.print_banner() From 682450755f44d6d3e9c4e9bf863a0d687952ca71 Mon Sep 17 00:00:00 2001 From: Olivier Booklage Date: Sat, 16 May 2026 14:57:02 +0200 Subject: [PATCH 2/2] Avoid duplicating LD_LIBRARY_PATH entries Skip prepending a directory that is already on LD_LIBRARY_PATH, so a repeated import of run.py does not bloat the variable. Addresses review feedback on #1826. --- run.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/run.py b/run.py index 03a6289..6fa4d85 100644 --- a/run.py +++ b/run.py @@ -52,10 +52,13 @@ if sys.platform.startswith("linux"): _lib_dir = os.path.join(_nvidia_dir, _pkg, "lib") if not os.path.isdir(_lib_dir): continue - # Also expose the directory to child processes - os.environ["LD_LIBRARY_PATH"] = ( - _lib_dir + os.pathsep + os.environ.get("LD_LIBRARY_PATH", "") - ) + # Also expose the directory to child processes, without + # duplicating an entry that is already present. + _ldp = os.environ.get("LD_LIBRARY_PATH", "") + if _lib_dir not in _ldp.split(os.pathsep): + os.environ["LD_LIBRARY_PATH"] = ( + _lib_dir + (os.pathsep + _ldp if _ldp else "") + ) for _so in sorted(glob.glob(os.path.join(_lib_dir, "lib*.so*"))): try: ctypes.CDLL(_so, mode=ctypes.RTLD_GLOBAL)