From c89a52033cfc92c0d79c99a49a56ad13498b49e8 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 20 May 2026 10:43:55 -0400 Subject: [PATCH 1/2] Add diagnostics --- cuda_bindings/cuda/bindings/nvml.pyx | 19 +++ cuda_core/tests/system/test_system_system.py | 164 +++++++++++++++++++ 2 files changed, 183 insertions(+) diff --git a/cuda_bindings/cuda/bindings/nvml.pyx b/cuda_bindings/cuda/bindings/nvml.pyx index d2596d72ebf..4f258edbdbc 100644 --- a/cuda_bindings/cuda/bindings/nvml.pyx +++ b/cuda_bindings/cuda/bindings/nvml.pyx @@ -21638,6 +21638,25 @@ cpdef str system_get_process_name(unsigned int pid): return cpython.PyUnicode_FromString(name) +cpdef bytes system_get_process_name_bytes(unsigned int pid): + """Gets name of the process with provided process id. + + Args: + pid (unsigned int): The identifier of the process. + + Returns: + char: Reference in which to return the process name. + + .. seealso:: `nvmlSystemGetProcessName` + """ + cdef unsigned int length = 1024 + cdef char[1024] name + with nogil: + __status__ = nvmlSystemGetProcessName(pid, name, length) + check_status(__status__) + return bytes(name) + + cpdef object system_get_hic_version(): """Retrieves the IDs and firmware versions for any Host Interface Cards (HICs) in the system. diff --git a/cuda_core/tests/system/test_system_system.py b/cuda_core/tests/system/test_system_system.py index 729e4b26244..372193740c8 100644 --- a/cuda_core/tests/system/test_system_system.py +++ b/cuda_core/tests/system/test_system_system.py @@ -3,7 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 +import contextlib +import locale import os +import shutil +import subprocess +import sys import pytest @@ -18,6 +23,152 @@ from .conftest import skip_if_nvml_unsupported +def _detect_wsl() -> bool: + if any(var in os.environ for var in ("WSL_DISTRO_NAME", "WSL_INTEROP", "WSLENV")): + return True + try: + with open("/proc/version", encoding="utf-8", errors="replace") as f: + version = f.read().lower() + except OSError: + return False + return "microsoft" in version or "wsl" in version + + +def _gather_wsl_host_info() -> list[str]: + info: list[str] = ["=== Windows host (via WSL interop) ==="] + + cmd_exe = shutil.which("cmd.exe") or "/mnt/c/Windows/System32/cmd.exe" + powershell = shutil.which("powershell.exe") or "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe" + + # Active console code page via cmd.exe. + try: + result = subprocess.run( # noqa: S603 + [cmd_exe, "/c", "chcp"], + capture_output=True, + text=True, + timeout=15, + cwd="/", + ) + info.append(f"cmd.exe chcp rc={result.returncode}") + if result.stdout: + info.append(f" stdout: {result.stdout.strip()!r}") + if result.stderr: + info.append(f" stderr: {result.stderr.strip()!r}") + except (OSError, subprocess.SubprocessError) as e: + info.append(f"cmd.exe chcp failed: {e!r}") + + # Richer culture / code page info via PowerShell. + ps_script = ";".join( + [ + "$OutputEncoding=[Text.Encoding]::UTF8", + "Write-Output ('Culture=' + (Get-Culture).Name)", + "Write-Output ('UICulture=' + (Get-UICulture).Name)", + "Write-Output ('SystemLocale=' + (Get-WinSystemLocale).Name)", + "Write-Output ('ConsoleOutputCP=' + [Console]::OutputEncoding.WebName)", + "Write-Output ('ConsoleInputCP=' + [Console]::InputEncoding.WebName)", + ( + "Write-Output ('ANSICodePage=' + " + "[System.Globalization.CultureInfo]::CurrentCulture.TextInfo.ANSICodePage)" + ), + ("Write-Output ('OEMCodePage=' + [System.Globalization.CultureInfo]::CurrentCulture.TextInfo.OEMCodePage)"), + "Write-Output ('OSVersion=' + [Environment]::OSVersion.VersionString)", + ] + ) + try: + result = subprocess.run( # noqa: S603 + [powershell, "-NoProfile", "-NonInteractive", "-Command", ps_script], + capture_output=True, + text=True, + timeout=30, + cwd="/", + ) + info.append(f"powershell.exe rc={result.returncode}") + for line in result.stdout.splitlines(): + info.append(f" {line.strip()}") + if result.stderr.strip(): + info.append(f" stderr: {result.stderr.strip()!r}") + except (OSError, subprocess.SubprocessError) as e: + info.append(f"powershell.exe call failed: {e!r}") + + return info + + +def _print_locale_diagnostics() -> None: + lines: list[str] = ["=== System / locale diagnostics ==="] + lines.append(f"sys.platform: {sys.platform}") + lines.append(f"sys.version: {sys.version.splitlines()[0]}") + lines.append(f"sys.getdefaultencoding(): {sys.getdefaultencoding()!r}") + lines.append(f"sys.getfilesystemencoding(): {sys.getfilesystemencoding()!r}") + lines.append(f"sys.getfilesystemencodeerrors(): {sys.getfilesystemencodeerrors()!r}") + lines.append(f"sys.stdout.encoding: {getattr(sys.stdout, 'encoding', None)!r}") + lines.append(f"sys.stderr.encoding: {getattr(sys.stderr, 'encoding', None)!r}") + lines.append(f"sys.flags.utf8_mode: {sys.flags.utf8_mode}") + + lines.append(f"locale.getpreferredencoding(False): {locale.getpreferredencoding(False)!r}") + lines.append(f"locale.getpreferredencoding(True): {locale.getpreferredencoding(True)!r}") + with contextlib.suppress(AttributeError): + lines.append(f"locale.getencoding(): {locale.getencoding()!r}") + try: + lines.append(f"locale.getlocale(): {locale.getlocale()!r}") + except (locale.Error, ValueError) as e: + lines.append(f"locale.getlocale() error: {e!r}") + + for cat_name in ( + "LC_ALL", + "LC_CTYPE", + "LC_COLLATE", + "LC_MESSAGES", + "LC_MONETARY", + "LC_NUMERIC", + "LC_TIME", + ): + cat = getattr(locale, cat_name, None) + if cat is None: + continue + try: + lines.append(f"locale.getlocale({cat_name}): {locale.getlocale(cat)!r}") + except (locale.Error, ValueError, TypeError) as e: + lines.append(f"locale.getlocale({cat_name}) error: {e!r}") + try: + lines.append(f"locale.setlocale({cat_name}, None): {locale.setlocale(cat, None)!r}") + except (locale.Error, ValueError, TypeError) as e: + lines.append(f"locale.setlocale({cat_name}, None) error: {e!r}") + + for var in ( + "LANG", + "LANGUAGE", + "LC_ALL", + "LC_CTYPE", + "LC_COLLATE", + "LC_MESSAGES", + "LC_MONETARY", + "LC_NUMERIC", + "LC_TIME", + "PYTHONUTF8", + "PYTHONIOENCODING", + "PYTHONLEGACYWINDOWSFSENCODING", + ): + lines.append(f"env {var}={os.environ.get(var, '')!r}") + + try: + with open("/proc/version", encoding="utf-8", errors="replace") as f: + lines.append(f"/proc/version: {f.read().strip()!r}") + except OSError as e: + lines.append(f"/proc/version: ") + + for var in ("WSL_DISTRO_NAME", "WSL_INTEROP", "WSLENV"): + if var in os.environ: + lines.append(f"env {var}={os.environ[var]!r}") + + if _detect_wsl(): + lines.extend(_gather_wsl_host_info()) + else: + lines.append("WSL not detected; skipping Windows host probe") + + lines.append("=== end diagnostics ===") + print("\n".join(lines), flush=True) + + def test_user_mode_driver_version(): umd = system.get_user_mode_driver_version() assert isinstance(umd, tuple) @@ -62,11 +213,24 @@ def test_nvml_version(): @skip_if_nvml_unsupported def test_get_process_name(): + _print_locale_diagnostics() + + from cuda.bindings import nvml + + nvml.init_v2() + print("BYTES:", repr(nvml.system_get_process_name_bytes(os.getpid()))) + try: process_name = system.get_process_name(os.getpid()) except system.NotFoundError: pytest.skip("Process not found") + print(f"process_name: {process_name!r}", flush=True) + print( + f"process_name.encode('utf-8', 'backslashreplace'): {process_name.encode('utf-8', 'backslashreplace')!r}", + flush=True, + ) + assert isinstance(process_name, str) assert "python" in process_name From e71777510b6c6e2465a9c8b41e0eb763eb62da79 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 20 May 2026 11:05:59 -0400 Subject: [PATCH 2/2] Adjust test matrix --- ci/test-matrix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/test-matrix.yml b/ci/test-matrix.yml index 35f02847ed7..0be26ee22b9 100644 --- a/ci/test-matrix.yml +++ b/ci/test-matrix.yml @@ -60,7 +60,7 @@ linux: - { ARCH: 'amd64', PY_VER: '3.13', CUDA_VER: '13.2.1', LOCAL_CTK: '1', GPU: 'h100', GPU_COUNT: '1', DRIVER: 'latest' } - { ARCH: 'amd64', PY_VER: '3.14', CUDA_VER: '13.2.1', LOCAL_CTK: '1', GPU: 't4', GPU_COUNT: '2', DRIVER: 'latest' } - { ARCH: 'amd64', PY_VER: '3.14t', CUDA_VER: '13.2.1', LOCAL_CTK: '1', GPU: 'h100', GPU_COUNT: '2', DRIVER: 'latest' } - - { ARCH: 'amd64', PY_VER: '3.11', CUDA_VER: '12.9.1', LOCAL_CTK: '0', GPU: 't4', GPU_COUNT: '1', DRIVER: 'latest', FLAVOR: 'wsl' } + - { ARCH: 'amd64', PY_VER: '3.11', CUDA_VER: '12.9.1', LOCAL_CTK: '1', GPU: 't4', GPU_COUNT: '1', DRIVER: 'latest', FLAVOR: 'wsl' } - { ARCH: 'amd64', PY_VER: '3.12', CUDA_VER: '13.2.1', LOCAL_CTK: '0', GPU: 'rtx4090', GPU_COUNT: '1', DRIVER: 'latest', FLAVOR: 'wsl' } nightly: # nightly-pytorch