From 18ebb61e30002c9f13d1902108384d06351e47e7 Mon Sep 17 00:00:00 2001 From: LeSingh1 Date: Tue, 4 Aug 2026 15:36:27 -0700 Subject: [PATCH] Query the newest DLL first in the Windows already-loaded check `windows_dlls` is tabulated oldest-first, and every other entry point reverses it "to achieve new -> old search order": `load_with_system_search()` on Windows, and both `check_if_already_loaded_from_elsewhere()` and `load_with_system_search()` on Linux, which share `_candidate_sonames()`. The Windows `check_if_already_loaded_from_elsewhere()` iterates `desc.windows_dlls` forward instead. For a library present in more than one version it therefore reports the oldest already-loaded one, while the system search on the same platform, and both paths on Linux, prefer the newest. Since the already-loaded check runs first, that is the version callers get. The new test is Windows-only: `load_dl_windows` imports `ctypes.wintypes` and requires `ctypes.windll` at module scope, so it cannot be imported at all on other platforms. --- .../_dynamic_libs/load_dl_windows.py | 4 +- cuda_pathfinder/tests/test_load_dl_windows.py | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 cuda_pathfinder/tests/test_load_dl_windows.py diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index e9cfbb52366..09ab8719d36 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -121,7 +121,9 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.wintypes.HMODULE) def check_if_already_loaded_from_elsewhere(desc: LibDescriptor, have_abs_path: bool) -> LoadedDL | None: - for dll_name in desc.windows_dlls: + # Reverse tabulated names to achieve new -> old search order, matching + # load_with_system_search() below and both Linux entry points. + for dll_name in reversed(desc.windows_dlls): handle = kernel32.GetModuleHandleW(dll_name) if handle: abs_path = abs_path_for_dynamic_library(desc.name, handle) diff --git a/cuda_pathfinder/tests/test_load_dl_windows.py b/cuda_pathfinder/tests/test_load_dl_windows.py new file mode 100644 index 00000000000..efd58a6bdc5 --- /dev/null +++ b/cuda_pathfinder/tests/test_load_dl_windows.py @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import sys + +import pytest + +from cuda.pathfinder._dynamic_libs.descriptor_catalog import DescriptorSpec + +# load_dl_windows imports ctypes.wintypes and requires ctypes.windll at module +# scope, so it cannot even be imported elsewhere; keep the import inside the test. +pytestmark = pytest.mark.skipif(sys.platform != "win32", reason="Exercises the Windows-only DLL loader") + + +@pytest.mark.agent_authored(model="claude-opus-5") +def test_already_loaded_check_queries_newest_dll_first(monkeypatch): + """The already-loaded probe must use the same new -> old order as the system search. + + ``windows_dlls`` is tabulated oldest-first and every other entry point + reverses it, so querying it forward here would report the oldest loaded + version of a library that is present in more than one version. + """ + from cuda.pathfinder._dynamic_libs import load_dl_windows + + queried: list[str] = [] + + class FakeKernel32: + @staticmethod + def GetModuleHandleW(dll_name: str) -> int: + queried.append(dll_name) + return 0 # nothing is loaded, so every name is probed + + monkeypatch.setattr(load_dl_windows, "kernel32", FakeKernel32) + + desc = DescriptorSpec( + name="test_lib", + packaged_with="other", + windows_dlls=("testlib64_11.dll", "testlib64_12.dll", "testlib64_13.dll"), + ) + + assert load_dl_windows.check_if_already_loaded_from_elsewhere(desc, False) is None + assert queried == ["testlib64_13.dll", "testlib64_12.dll", "testlib64_11.dll"]