Skip to content

Commit 77c8417

Browse files
committed
Add callback thread-safety regression test for cuda_bindings_12 (follow-up to #3308)
1 parent 7de298b commit 77c8417

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

‎cuda_bindings_12/docs/source/release/12.X.Y-notes.rst‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ Bug Fixes
2525
call and free the buffers allocated for getters.
2626
* ``get_cuda_native_handle`` preserves a ``KeyError`` raised inside a
2727
registered getter instead of reporting an unknown type.
28+
* Fixed a crash on free-threaded Python when callbacks are registered or
29+
unregistered from multiple threads at the same time. Access to the internal
30+
callback registry is now synchronized.
2831

2932
Packaging
3033
---------
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import threading
5+
6+
import pytest
7+
8+
from cuda.bindings import driver
9+
10+
NUM_THREADS = 16
11+
NUM_ITERATIONS = 500
12+
13+
14+
@pytest.mark.agent_authored(model="claude-sonnet-5-5")
15+
def test_async_notification_register_unregister_from_many_threads():
16+
(err,) = driver.cuInit(0)
17+
assert err == driver.CUresult.CUDA_SUCCESS
18+
err, device = driver.cuDeviceGet(0)
19+
assert err == driver.CUresult.CUDA_SUCCESS
20+
21+
barrier = threading.Barrier(NUM_THREADS)
22+
failures = []
23+
24+
def worker():
25+
try:
26+
barrier.wait()
27+
for _ in range(NUM_ITERATIONS):
28+
err, handle = driver.cuDeviceRegisterAsyncNotification(device, 0, 0)
29+
assert err == driver.CUresult.CUDA_SUCCESS
30+
(err,) = driver.cuDeviceUnregisterAsyncNotification(device, handle)
31+
assert err == driver.CUresult.CUDA_SUCCESS
32+
except BaseException as e:
33+
failures.append(e)
34+
35+
threads = [threading.Thread(target=worker) for _ in range(NUM_THREADS)]
36+
for t in threads:
37+
t.start()
38+
for t in threads:
39+
t.join()
40+
41+
assert not failures, failures

0 commit comments

Comments
 (0)