Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions cuda_bindings_12/cuda/bindings/_internal/driver_linux.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
#
# This code was automatically generated with version 12.9.0. Do not modify it directly.
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=c4957d188c7c3258823fd50e2eb0cba162810911af7294ab726f1e49769642c8
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=d382464130e581b718a589e652053c30057e65ddc824b2c79a903341858f1e88


# <<<< PREAMBLE CONTENT >>>>
Expand Down Expand Up @@ -1894,19 +1894,19 @@ cdef int _init_driver() except -1 nogil:
cuGetProcAddress_v2('cuGreenCtxStreamCreate', <void **>&__cuGreenCtxStreamCreate, 12050, ptds_mode, NULL)

global __cuLogsRegisterCallback
cuGetProcAddress_v2('cuLogsRegisterCallback', <void **>&__cuLogsRegisterCallback, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsRegisterCallback', <void **>&__cuLogsRegisterCallback, 12090, ptds_mode, NULL)

global __cuLogsUnregisterCallback
cuGetProcAddress_v2('cuLogsUnregisterCallback', <void **>&__cuLogsUnregisterCallback, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsUnregisterCallback', <void **>&__cuLogsUnregisterCallback, 12090, ptds_mode, NULL)

global __cuLogsCurrent
cuGetProcAddress_v2('cuLogsCurrent', <void **>&__cuLogsCurrent, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsCurrent', <void **>&__cuLogsCurrent, 12090, ptds_mode, NULL)

global __cuLogsDumpToFile
cuGetProcAddress_v2('cuLogsDumpToFile', <void **>&__cuLogsDumpToFile, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsDumpToFile', <void **>&__cuLogsDumpToFile, 12090, ptds_mode, NULL)

global __cuLogsDumpToMemory
cuGetProcAddress_v2('cuLogsDumpToMemory', <void **>&__cuLogsDumpToMemory, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsDumpToMemory', <void **>&__cuLogsDumpToMemory, 12090, ptds_mode, NULL)

global __cuCheckpointProcessGetRestoreThreadId
cuGetProcAddress_v2('cuCheckpointProcessGetRestoreThreadId', <void **>&__cuCheckpointProcessGetRestoreThreadId, 12080, ptds_mode, NULL)
Expand Down
12 changes: 6 additions & 6 deletions cuda_bindings_12/cuda/bindings/_internal/driver_windows.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: Apache-2.0
#
# This code was automatically generated with version 12.9.0. Do not modify it directly.
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=d36a59b7d4c8939f88b07a4600cbd4251a2ed69571b425bb6009a626cfd4dc3e
# CYTHON-BINDINGS-GENERATED-DO-NOT-MODIFY-THIS-FILE: format=1; content-sha256=895c345db6512915d2c6c9f27757175413ce053e7356b6eeb890478159cdc918


# <<<< PREAMBLE CONTENT >>>>
Expand Down Expand Up @@ -1897,19 +1897,19 @@ cdef int _init_driver() except -1 nogil:
cuGetProcAddress_v2('cuGreenCtxStreamCreate', <void **>&__cuGreenCtxStreamCreate, 12050, ptds_mode, NULL)

global __cuLogsRegisterCallback
cuGetProcAddress_v2('cuLogsRegisterCallback', <void **>&__cuLogsRegisterCallback, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsRegisterCallback', <void **>&__cuLogsRegisterCallback, 12090, ptds_mode, NULL)

global __cuLogsUnregisterCallback
cuGetProcAddress_v2('cuLogsUnregisterCallback', <void **>&__cuLogsUnregisterCallback, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsUnregisterCallback', <void **>&__cuLogsUnregisterCallback, 12090, ptds_mode, NULL)

global __cuLogsCurrent
cuGetProcAddress_v2('cuLogsCurrent', <void **>&__cuLogsCurrent, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsCurrent', <void **>&__cuLogsCurrent, 12090, ptds_mode, NULL)

global __cuLogsDumpToFile
cuGetProcAddress_v2('cuLogsDumpToFile', <void **>&__cuLogsDumpToFile, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsDumpToFile', <void **>&__cuLogsDumpToFile, 12090, ptds_mode, NULL)

global __cuLogsDumpToMemory
cuGetProcAddress_v2('cuLogsDumpToMemory', <void **>&__cuLogsDumpToMemory, 12080, ptds_mode, NULL)
cuGetProcAddress_v2('cuLogsDumpToMemory', <void **>&__cuLogsDumpToMemory, 12090, ptds_mode, NULL)

global __cuCheckpointProcessGetRestoreThreadId
cuGetProcAddress_v2('cuCheckpointProcessGetRestoreThreadId', <void **>&__cuCheckpointProcessGetRestoreThreadId, 12080, ptds_mode, NULL)
Expand Down
36 changes: 36 additions & 0 deletions cuda_bindings_12/tests/test_cuda.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@
# SPDX-License-Identifier: Apache-2.0

import ctypes
import os
import platform
import shutil
import tempfile
import textwrap

import numpy as np
import pytest

import cuda.cuda as cuda
from cuda.bindings import driver
from cuda.bindings._internal.utils import FunctionNotFoundError
from cuda_python_test_helpers import driver_version_less_than
from cuda_python_test_helpers.memory import (
POOL_SIZE,
Expand Down Expand Up @@ -1153,6 +1156,39 @@ def test_cuCheckpointProcessGetState_failure():
assert state is None


@pytest.mark.skipif(
driver_version_less_than(12090),
reason="cuLogs* functions were introduced in CUDA 12.9",
)
def test_culogs_functions():
try:
err, callback_handle = cuda.cuLogsRegisterCallback(0, None)

@coderabbitai coderabbitai Bot Nov 5, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Quick win

Supported by static analysis

Script executed:

rg -n 'cuLogsCallbackWrapper|cuLogsRegisterCallback|cuLogsUnregisterCallback' cuda_bindings_12/cuda/bindings/driver.pyx
sed -n '1155,1195p' cuda_bindings_12/tests/test_cuda.py

Repository: NVIDIA/cuda-python

Length of output: 2131


Script executed:

sed -n '50970,51060p' cuda_bindings_12/cuda/bindings/driver.pyx
rg -n -F -e 'cuLogsRegisterCallback' -e 'cuLogsCallbackWrapper' -- cuda_bindings_12/cuda/bindings/driver.pyx || test "$?" -eq 1

Repository: NVIDIA/cuda-python

Length of output: 3871


important: Register a live callback, not None.

cuLogsRegisterCallback(0, None) stores a NULL user callback. The binding always registers cuLogsCallbackWrapper with the driver, and that wrapper calls the stored callback without a NULL check (cuda_bindings_12/cuda/bindings/driver.pyx:50976). If the driver delivers a log message while this callback is registered, the wrapper calls a NULL function pointer and can crash the test process.

Register a no-op callback instead:

Suggested fix

--- "a/cuda_bindings_12/tests/test_cuda.py"
+++ "b/cuda_bindings_12/tests/test_cuda.py"
@@ -1156,13 +1156,16 @@
     assert state is None
 
 
+def _noop_culogs_callback(user_data, log_level, message, length):
+    pass
+
 @pytest.mark.skipif(
     driver_version_less_than(12090),
     reason="cuLogs* functions were introduced in CUDA 12.9",
 )
 def test_culogs_functions():
     try:
-        err, callback_handle = cuda.cuLogsRegisterCallback(0, None)
+        err, callback_handle = cuda.cuLogsRegisterCallback(_noop_culogs_callback, None)
         assert err == cuda.CUresult.CUDA_SUCCESS
 
         err, _ = cuda.cuLogsCurrent(0)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the test case crashes we will catch that in CI. Adding no-op will make the test case complicated.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lijinf2 important: Understood. I won’t press for the no-op callback. The reported crash risk depends on the driver delivering a log message, so CI can pass without exercising that path.

You are interacting with an AI system.

assert err == cuda.CUresult.CUDA_SUCCESS

err, _ = cuda.cuLogsCurrent(0)
assert err == cuda.CUresult.CUDA_SUCCESS

with tempfile.NamedTemporaryFile(delete=False) as f:
log_path = f.name
try:
err, _ = cuda.cuLogsDumpToFile(None, log_path.encode(), 0)
assert err == cuda.CUresult.CUDA_SUCCESS
finally:
os.remove(log_path)

# cuLogsDumpToMemory's own docstring states the driver's internal log
# buffer is capped at 25600 bytes, so a buffer of that size is always
# large enough to hold the dump without risking a buffer overrun.
buf = bytearray(25600)
err, _, _ = cuda.cuLogsDumpToMemory(None, buf, len(buf), 0)
assert err == cuda.CUresult.CUDA_SUCCESS

(err,) = cuda.cuLogsUnregisterCallback(callback_handle)

@coderabbitai coderabbitai Bot Nov 5, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Quick win

important: Unregister the callback on failure.

If a later cuLogs call raises FunctionNotFoundError or an assertion fails, this line is skipped and the callback remains registered for subsequent tests. A subsequent log can then crash the process through the null callback. Unregister the callback in a finally block after successful registration. (raw.githubusercontent.com)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ok to crash because this is a test case not core code.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lijinf2 suggestion: Understood. I will leave callback cleanup to your discretion. The concern is test isolation, not core-code safety.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to match existing code on the 12.9.x branch in this PR. This isn't significant enough I think to track as a follow-on.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

assert err == cuda.CUresult.CUDA_SUCCESS
except FunctionNotFoundError as e:
pytest.fail(f"cuLogs* function unexpectedly not found on the driver: {e}")


def test_private_function_pointer_inspector():
from cuda.bindings._internal.driver import _inspect_function_pointer

Expand Down
Loading