From 35afc11c04539ba4a369da6299b1f62efa6ca90f Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:07:12 -0400 Subject: [PATCH 1/4] fix(pathfinder): keep canary probes script-safe Run the CTK canary probe via a dedicated module subprocess so it still gets a fresh interpreter and independent loader state without re-entering the caller's script as __main__. Made-with: Cursor --- .../_dynamic_libs/canary_probe_subprocess.py | 14 +++ .../_dynamic_libs/load_nvidia_dynamic_lib.py | 50 +++++++-- .../_headers/find_nvidia_headers.py | 2 +- .../docs/source/release/1.4.0-notes.rst | 4 +- .../tests/test_ctk_root_discovery.py | 103 +++++++++++++++--- 5 files changed, 147 insertions(+), 26 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/canary_probe_subprocess.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/canary_probe_subprocess.py index ab50c37de4..1a64bdb9f0 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/canary_probe_subprocess.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/canary_probe_subprocess.py @@ -2,6 +2,8 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +import sys +from collections.abc import Sequence import json from cuda.pathfinder._dynamic_libs.lib_descriptor import LIB_DESCRIPTORS @@ -27,3 +29,15 @@ def _probe_canary_abs_path(libname: str) -> str | None: def probe_canary_abs_path_and_print_json(libname: str) -> None: print(json.dumps(_probe_canary_abs_path(libname))) + + +def main(argv: Sequence[str] | None = None) -> int: + args = list(sys.argv[1:] if argv is None else argv) + if len(args) != 1: + raise SystemExit("Usage: python -m cuda.pathfinder._dynamic_libs.canary_probe_subprocess ") + probe_canary_abs_path_and_print_json(args[0]) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index c40dffde15..5ffbf2bc26 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -6,10 +6,10 @@ import functools import json import struct +import subprocess import sys from typing import TYPE_CHECKING -from cuda.pathfinder._dynamic_libs.canary_probe_subprocess import probe_canary_abs_path_and_print_json from cuda.pathfinder._dynamic_libs.lib_descriptor import LIB_DESCRIPTORS from cuda.pathfinder._dynamic_libs.load_dl_common import ( DynamicLibNotAvailableError, @@ -28,7 +28,6 @@ run_find_steps, ) from cuda.pathfinder._utils.platform_aware import IS_WINDOWS -from cuda.pathfinder._utils.spawned_process_runner import run_in_spawned_child_process if TYPE_CHECKING: from cuda.pathfinder._dynamic_libs.lib_descriptor import LibDescriptor @@ -40,6 +39,8 @@ name for name, desc in LIB_DESCRIPTORS.items() if (desc.windows_dlls if IS_WINDOWS else desc.linux_sonames) ) _PLATFORM_NAME = "Windows" if IS_WINDOWS else "Linux" +_CANARY_PROBE_MODULE = "cuda.pathfinder._dynamic_libs.canary_probe_subprocess" +_CANARY_PROBE_TIMEOUT_SECONDS = 10.0 # Driver libraries: shipped with the NVIDIA display driver, always on the # system linker path. These skip all CTK search steps (site-packages, @@ -67,15 +68,46 @@ def _load_driver_lib_no_cache(desc: LibDescriptor) -> LoadedDL: ) +def _coerce_subprocess_output(output: str | bytes | None) -> str: + if isinstance(output, bytes): + return output.decode(errors="replace") + return "" if output is None else output + + +def _raise_canary_probe_child_process_error( + *, + returncode: int | None = None, + timeout: float | None = None, + stderr: str | bytes | None = None, +) -> None: + if timeout is None: + error_line = f"Canary probe child process exited with code {returncode}." + else: + error_line = f"Canary probe child process timed out after {timeout} seconds." + raise ChildProcessError( + f"{error_line}\n" + "--- stderr-from-child-process ---\n" + f"{_coerce_subprocess_output(stderr)}" + "\n" + ) + + @functools.cache def _resolve_system_loaded_abs_path_in_subprocess(libname: str) -> str | None: - """Resolve a canary library's absolute path in a spawned child process.""" - result = run_in_spawned_child_process( - probe_canary_abs_path_and_print_json, - args=(libname,), - timeout=10.0, - rethrow=True, - ) + """Resolve a canary library's absolute path in a fresh Python subprocess.""" + try: + result = subprocess.run( + [sys.executable, "-m", _CANARY_PROBE_MODULE, libname], + capture_output=True, + text=True, + timeout=_CANARY_PROBE_TIMEOUT_SECONDS, + check=False, + ) + except subprocess.TimeoutExpired as exc: + _raise_canary_probe_child_process_error(timeout=exc.timeout, stderr=exc.stderr) + + if result.returncode != 0: + _raise_canary_probe_child_process_error(returncode=result.returncode, stderr=result.stderr) # Use the final non-empty line in case earlier output lines are emitted. lines = [line for line in result.stdout.splitlines() if line.strip()] diff --git a/cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py b/cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py index b6118db64d..f47eb2c9d8 100644 --- a/cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py +++ b/cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py @@ -115,7 +115,7 @@ def find_via_ctk_root_canary(desc: HeaderDescriptor) -> LocatedHeaderDir | None: """Try CTK header lookup via CTK-root canary probing. Skips immediately if the descriptor does not opt in (``use_ctk_root_canary``). - Otherwise, system-loads ``cudart`` in a spawned child process, derives + Otherwise, system-loads ``cudart`` in a dedicated Python subprocess, derives CTK root from the resolved library path, and searches the expected include layout under that root. """ diff --git a/cuda_pathfinder/docs/source/release/1.4.0-notes.rst b/cuda_pathfinder/docs/source/release/1.4.0-notes.rst index bcfd202b7d..621f6eae26 100644 --- a/cuda_pathfinder/docs/source/release/1.4.0-notes.rst +++ b/cuda_pathfinder/docs/source/release/1.4.0-notes.rst @@ -12,8 +12,8 @@ Highlights ---------- * Add CTK root canary probing for non-standard-path libraries in - ``load_nvidia_dynamic_lib()`` (notably ``nvvm``), including spawned child - process isolation for the canary probe. + ``load_nvidia_dynamic_lib()`` (notably ``nvvm``), including dedicated + subprocess isolation for the canary probe. (`PR #1595 `_) * Restore backward-compatible exception behavior for diff --git a/cuda_pathfinder/tests/test_ctk_root_discovery.py b/cuda_pathfinder/tests/test_ctk_root_discovery.py index bcfce30c25..9bc55959b6 100644 --- a/cuda_pathfinder/tests/test_ctk_root_discovery.py +++ b/cuda_pathfinder/tests/test_ctk_root_discovery.py @@ -2,6 +2,12 @@ # SPDX-License-Identifier: Apache-2.0 +import os +import subprocess +import sys +import textwrap +from pathlib import Path + import pytest from cuda.pathfinder._dynamic_libs import load_nvidia_dynamic_lib as load_mod @@ -24,6 +30,7 @@ _MODULE = "cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib" _STEPS_MODULE = "cuda.pathfinder._dynamic_libs.search_steps" +_PACKAGE_ROOT = Path(__file__).resolve().parents[1] def _ctx(libname: str = "nvvm") -> SearchContext: @@ -184,53 +191,121 @@ def test_try_via_ctk_root_regular_lib(tmp_path): def test_subprocess_probe_returns_abs_path_on_string_payload(mocker): - result = mocker.Mock(stdout='"/usr/local/cuda/lib64/libcudart.so.13"\n') - run_mock = mocker.patch(f"{_MODULE}.run_in_spawned_child_process", return_value=result) + result = subprocess.CompletedProcess( + args=[], + returncode=0, + stdout='"/usr/local/cuda/lib64/libcudart.so.13"\n', + stderr="", + ) + run_mock = mocker.patch(f"{_MODULE}.subprocess.run", return_value=result) assert _resolve_system_loaded_abs_path_in_subprocess("cudart") == "/usr/local/cuda/lib64/libcudart.so.13" - assert run_mock.call_args.kwargs.get("rethrow") is True + run_mock.assert_called_once_with( + [sys.executable, "-m", "cuda.pathfinder._dynamic_libs.canary_probe_subprocess", "cudart"], + capture_output=True, + text=True, + timeout=10.0, + check=False, + ) def test_subprocess_probe_returns_none_on_null_payload(mocker): - result = mocker.Mock(stdout="null\n") - mocker.patch(f"{_MODULE}.run_in_spawned_child_process", return_value=result) + result = subprocess.CompletedProcess(args=[], returncode=0, stdout="null\n", stderr="") + mocker.patch(f"{_MODULE}.subprocess.run", return_value=result) assert _resolve_system_loaded_abs_path_in_subprocess("cudart") is None def test_subprocess_probe_raises_on_child_failure(mocker): + result = subprocess.CompletedProcess(args=[], returncode=1, stdout="", stderr="child failed\n") + mocker.patch(f"{_MODULE}.subprocess.run", return_value=result) + + with pytest.raises(ChildProcessError, match="child failed"): + _resolve_system_loaded_abs_path_in_subprocess("cudart") + + +def test_subprocess_probe_raises_on_timeout(mocker): mocker.patch( - f"{_MODULE}.run_in_spawned_child_process", - side_effect=ChildProcessError("child failed"), + f"{_MODULE}.subprocess.run", + side_effect=subprocess.TimeoutExpired(cmd=["python"], timeout=10.0, stderr="probe hung\n"), ) - with pytest.raises(ChildProcessError, match="child failed"): + with pytest.raises(ChildProcessError, match="timed out after 10.0 seconds"): _resolve_system_loaded_abs_path_in_subprocess("cudart") def test_subprocess_probe_raises_on_empty_stdout(mocker): - result = mocker.Mock(stdout=" \n \n") - mocker.patch(f"{_MODULE}.run_in_spawned_child_process", return_value=result) + result = subprocess.CompletedProcess(args=[], returncode=0, stdout=" \n \n", stderr="") + mocker.patch(f"{_MODULE}.subprocess.run", return_value=result) with pytest.raises(RuntimeError, match="produced no stdout payload"): _resolve_system_loaded_abs_path_in_subprocess("cudart") def test_subprocess_probe_raises_on_invalid_json_payload(mocker): - result = mocker.Mock(stdout="not-json\n") - mocker.patch(f"{_MODULE}.run_in_spawned_child_process", return_value=result) + result = subprocess.CompletedProcess(args=[], returncode=0, stdout="not-json\n", stderr="") + mocker.patch(f"{_MODULE}.subprocess.run", return_value=result) with pytest.raises(RuntimeError, match="invalid JSON payload"): _resolve_system_loaded_abs_path_in_subprocess("cudart") def test_subprocess_probe_raises_on_unexpected_json_payload(mocker): - result = mocker.Mock(stdout='{"path": "/usr/local/cuda/lib64/libcudart.so.13"}\n') - mocker.patch(f"{_MODULE}.run_in_spawned_child_process", return_value=result) + result = subprocess.CompletedProcess( + args=[], + returncode=0, + stdout='{"path": "/usr/local/cuda/lib64/libcudart.so.13"}\n', + stderr="", + ) + mocker.patch(f"{_MODULE}.subprocess.run", return_value=result) with pytest.raises(RuntimeError, match="unexpected payload"): _resolve_system_loaded_abs_path_in_subprocess("cudart") +def test_subprocess_probe_does_not_reenter_calling_script(tmp_path): + script_path = tmp_path / "call_probe.py" + run_count_path = tmp_path / "run_count.txt" + script_path.write_text( + textwrap.dedent( + f""" + from pathlib import Path + + from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import ( + _resolve_system_loaded_abs_path_in_subprocess, + ) + + marker_path = Path({str(run_count_path)!r}) + run_count = int(marker_path.read_text()) if marker_path.exists() else 0 + marker_path.write_text(str(run_count + 1)) + + try: + _resolve_system_loaded_abs_path_in_subprocess("not_a_real_lib") + except Exception: + pass + """ + ), + encoding="utf-8", + ) + env = os.environ.copy() + existing_pythonpath = env.get("PYTHONPATH") + env["PYTHONPATH"] = ( + str(_PACKAGE_ROOT) + if not existing_pythonpath + else os.pathsep.join((str(_PACKAGE_ROOT), existing_pythonpath)) + ) + + result = subprocess.run( + [sys.executable, str(script_path)], + capture_output=True, + text=True, + check=False, + env=env, + ) + + assert result.returncode == 0, result.stderr + assert run_count_path.read_text(encoding="utf-8") == "1" + + # --------------------------------------------------------------------------- # _try_ctk_root_canary # --------------------------------------------------------------------------- From 3f3614975c15cc1f3d395becd7e6ac6777286740 Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:13:25 -0400 Subject: [PATCH 2/4] fix(pathfinder): satisfy canary probe pre-commit hooks Mark the intentional subprocess launches as trusted inputs for Ruff's bandit checks and keep the affected files in hook-compliant import/format order. Made-with: Cursor --- .../pathfinder/_dynamic_libs/canary_probe_subprocess.py | 2 +- .../pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py | 2 +- cuda_pathfinder/tests/test_ctk_root_discovery.py | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/canary_probe_subprocess.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/canary_probe_subprocess.py index 1a64bdb9f0..d4112f9dfa 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/canary_probe_subprocess.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/canary_probe_subprocess.py @@ -2,9 +2,9 @@ # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +import json import sys from collections.abc import Sequence -import json from cuda.pathfinder._dynamic_libs.lib_descriptor import LIB_DESCRIPTORS from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError, LoadedDL diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 5ffbf2bc26..58d25294a3 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -96,7 +96,7 @@ def _raise_canary_probe_child_process_error( def _resolve_system_loaded_abs_path_in_subprocess(libname: str) -> str | None: """Resolve a canary library's absolute path in a fresh Python subprocess.""" try: - result = subprocess.run( + result = subprocess.run( # noqa: S603 - trusted argv: current interpreter + internal probe module [sys.executable, "-m", _CANARY_PROBE_MODULE, libname], capture_output=True, text=True, diff --git a/cuda_pathfinder/tests/test_ctk_root_discovery.py b/cuda_pathfinder/tests/test_ctk_root_discovery.py index 9bc55959b6..de1ad64dd3 100644 --- a/cuda_pathfinder/tests/test_ctk_root_discovery.py +++ b/cuda_pathfinder/tests/test_ctk_root_discovery.py @@ -289,12 +289,10 @@ def test_subprocess_probe_does_not_reenter_calling_script(tmp_path): env = os.environ.copy() existing_pythonpath = env.get("PYTHONPATH") env["PYTHONPATH"] = ( - str(_PACKAGE_ROOT) - if not existing_pythonpath - else os.pathsep.join((str(_PACKAGE_ROOT), existing_pythonpath)) + str(_PACKAGE_ROOT) if not existing_pythonpath else os.pathsep.join((str(_PACKAGE_ROOT), existing_pythonpath)) ) - result = subprocess.run( + result = subprocess.run( # noqa: S603 - trusted argv: current interpreter + temp script created by this test [sys.executable, str(script_path)], capture_output=True, text=True, From b702b7a2029eb33d745f51ac6d69c71c9418f5ed Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Mon, 16 Mar 2026 13:31:25 -0400 Subject: [PATCH 3/4] fix(pathfinder): anchor canary probe import root Run the canary subprocess from the parent package's import root so wheel-based CI tests do not accidentally resolve `cuda.pathfinder` from the checkout tree and fail on missing generated files. Made-with: Cursor --- .../cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py | 3 +++ cuda_pathfinder/tests/test_ctk_root_discovery.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 58d25294a3..f1d82f3e71 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -8,6 +8,7 @@ import struct import subprocess import sys +from pathlib import Path from typing import TYPE_CHECKING from cuda.pathfinder._dynamic_libs.lib_descriptor import LIB_DESCRIPTORS @@ -41,6 +42,7 @@ _PLATFORM_NAME = "Windows" if IS_WINDOWS else "Linux" _CANARY_PROBE_MODULE = "cuda.pathfinder._dynamic_libs.canary_probe_subprocess" _CANARY_PROBE_TIMEOUT_SECONDS = 10.0 +_CANARY_PROBE_IMPORT_ROOT = Path(__file__).resolve().parents[3] # Driver libraries: shipped with the NVIDIA display driver, always on the # system linker path. These skip all CTK search steps (site-packages, @@ -102,6 +104,7 @@ def _resolve_system_loaded_abs_path_in_subprocess(libname: str) -> str | None: text=True, timeout=_CANARY_PROBE_TIMEOUT_SECONDS, check=False, + cwd=_CANARY_PROBE_IMPORT_ROOT, ) except subprocess.TimeoutExpired as exc: _raise_canary_probe_child_process_error(timeout=exc.timeout, stderr=exc.stderr) diff --git a/cuda_pathfinder/tests/test_ctk_root_discovery.py b/cuda_pathfinder/tests/test_ctk_root_discovery.py index de1ad64dd3..d5d4ebffb3 100644 --- a/cuda_pathfinder/tests/test_ctk_root_discovery.py +++ b/cuda_pathfinder/tests/test_ctk_root_discovery.py @@ -30,7 +30,7 @@ _MODULE = "cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib" _STEPS_MODULE = "cuda.pathfinder._dynamic_libs.search_steps" -_PACKAGE_ROOT = Path(__file__).resolve().parents[1] +_PACKAGE_ROOT = Path(load_mod.__file__).resolve().parents[3] def _ctx(libname: str = "nvvm") -> SearchContext: @@ -206,6 +206,7 @@ def test_subprocess_probe_returns_abs_path_on_string_payload(mocker): text=True, timeout=10.0, check=False, + cwd=_PACKAGE_ROOT, ) From 8d78582935d850734689e120aa05251c647ccc86 Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:04:25 -0400 Subject: [PATCH 4/4] docs(pathfinder): address review feedback Use the requested fully-isolated subprocess wording, restore the historical 1.4.0 release note text, and add new 1.4.3 release notes for the script-safety and import-root fixes instead. Made-with: Cursor --- .../_headers/find_nvidia_headers.py | 2 +- .../docs/source/release/1.4.0-notes.rst | 4 ++-- .../docs/source/release/1.4.3-notes.rst | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 cuda_pathfinder/docs/source/release/1.4.3-notes.rst diff --git a/cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py b/cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py index f47eb2c9d8..6e2ae100d8 100644 --- a/cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py +++ b/cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py @@ -115,7 +115,7 @@ def find_via_ctk_root_canary(desc: HeaderDescriptor) -> LocatedHeaderDir | None: """Try CTK header lookup via CTK-root canary probing. Skips immediately if the descriptor does not opt in (``use_ctk_root_canary``). - Otherwise, system-loads ``cudart`` in a dedicated Python subprocess, derives + Otherwise, system-loads ``cudart`` in a fully isolated Python subprocess, derives CTK root from the resolved library path, and searches the expected include layout under that root. """ diff --git a/cuda_pathfinder/docs/source/release/1.4.0-notes.rst b/cuda_pathfinder/docs/source/release/1.4.0-notes.rst index 621f6eae26..bcfd202b7d 100644 --- a/cuda_pathfinder/docs/source/release/1.4.0-notes.rst +++ b/cuda_pathfinder/docs/source/release/1.4.0-notes.rst @@ -12,8 +12,8 @@ Highlights ---------- * Add CTK root canary probing for non-standard-path libraries in - ``load_nvidia_dynamic_lib()`` (notably ``nvvm``), including dedicated - subprocess isolation for the canary probe. + ``load_nvidia_dynamic_lib()`` (notably ``nvvm``), including spawned child + process isolation for the canary probe. (`PR #1595 `_) * Restore backward-compatible exception behavior for diff --git a/cuda_pathfinder/docs/source/release/1.4.3-notes.rst b/cuda_pathfinder/docs/source/release/1.4.3-notes.rst new file mode 100644 index 0000000000..bb75fd4e75 --- /dev/null +++ b/cuda_pathfinder/docs/source/release/1.4.3-notes.rst @@ -0,0 +1,22 @@ +.. SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +.. SPDX-License-Identifier: Apache-2.0 + +.. py:currentmodule:: cuda.pathfinder + +``cuda-pathfinder`` 1.4.3 Release notes +======================================= + +Highlights +---------- + +* Fix CTK canary probing when it is reached from plain Python scripts that do + not use an ``if __name__ == "__main__"`` guard. The canary now runs in a + fully isolated Python subprocess without re-entering the caller's script + during child-process startup. + (`PR #1768 `_) + +* Make the canary subprocess resolve ``cuda.pathfinder`` from the same import + root as the parent process. This avoids mixed source-tree versus wheel imports + in wheel-based test environments and keeps the probe behavior consistent + across source and installed-package workflows. + (`PR #1768 `_)