Summary
Two tests added by #2728 in cuda_core/tests/memory_ipc/test_errors.py fail on the free-threaded CI jobs (Test linux-aarch64 / Python 3.14t), where pytest-run-parallel executes each test body concurrently in several threads (the module sets pytestmark = pytest.mark.parallel_threads_limit(4)). One failure is a segmentation fault inside cuMemPoolDestroy; the other is a data race on the test class instance. Both reproduce on main itself, independent of the PR they were first noticed on.
Failure 1: SEGV in cuMemPoolDestroy from test_allocation_handle_forking_pickler_roundtrip
Observed on main for the #2728 merge commit bcfbe72c8c7 (run 34230002523, job 102076702071, CUDA 12.9.1 local, L4) and again on #2759 (run 34253228097, job 102163403217, CUDA 13.0.2 wheels, A100). The faulthandler dump is the same in both:
Fatal Python error: Segmentation fault
Stack (most recent call first):
File ".../cuda_core/tests/memory_ipc/test_errors.py", line 327 in test_allocation_handle_forking_pickler_roundtrip
File ".../cuda_core/tests/conftest.py", line 104 in wrapper
File ".../pytest_run_parallel/plugin.py", line 83 in closure
Current thread's C stack trace (most recent call first):
libcuda.so.1 ...
libcuda.so.1, at cuMemPoolDestroy+0x30
cuda/bindings/_bindings/cydriver...
cuda/core/cu13/_resource_handles...
cuda/core/cu13/_memory/_memory_pool...
Line 327 is the mr.close() in the test's finally. Each of the four threads creates its own IPC-enabled DeviceMemoryResource, reads mr.allocation_handle, round-trips it through multiprocessing.reduction.ForkingPickler, closes the restored handle, and destroys its pool. The crash is inside the driver's cuMemPoolDestroy while the other threads are exporting or destroying their own IPC pools. Whether this is a driver-level restriction on concurrent IPC pool export/destroy or a cuda.core teardown problem is not established; either way the test cannot run in parallel threads as written.
Failure 2: TestImportWrongMR.test_main[PinnedMR] pickles another thread's closed resource
Observed on #2759 (run 34253228097, job 102163403408, CUDA 13.3.0 local, L4). The test is marked flaky(reruns=2) and failed all three attempts:
RuntimeError: DeviceMemoryResource has been closed
when serializing cuda.core._memory._buffer.Buffer object
when serializing dict item 'buffer'
when serializing test_errors.TestImportWrongMR state
when serializing multiprocessing.context.Process object
ChildErrorHarness.test_main stores its fixtures on the instance (self.device, self.mr, self._extra_mrs, and self.buffer set by PARENT_ACTION) and spawns the child with target=self.child_main, which pickles self. pytest-run-parallel runs the four threads against the same test instance and the same function-scoped ipc_memory_resource value, so one thread pickles a Buffer whose resource another thread has already closed. The same shared-state pattern applies to every subclass of ChildErrorHarness in the file; this one just lost the race first.
Suggested fix
- Mark the
ChildErrorHarness subclasses and test_allocation_handle_forking_pickler_roundtrip @pytest.mark.thread_unsafe (reason: shared instance state and multiprocessing spawn; concurrent IPC pool export/destroy), or drop the module-level parallel_threads_limit(4) in favour of per-test marks.
- Separately investigate whether concurrent
cuMemPoolDestroy of IPC-enabled pools from several threads is supposed to be safe; if it is, the SEGV is a cuda.core bug in pool teardown rather than a test-only issue.
Environment
GitHub Actions, linux-aarch64, Python 3.14.7 free-threaded, cuda-bindings 13.x, pytest-run-parallel, CUDA 12.9.1 / 13.0.2 / 13.3.0.
Refs: #2728 (tests added), #2759 (where the failures were analysed).
@rluo8 and @seberg for viz
Summary
Two tests added by #2728 in
cuda_core/tests/memory_ipc/test_errors.pyfail on the free-threaded CI jobs (Test linux-aarch64 / Python 3.14t), where pytest-run-parallel executes each test body concurrently in several threads (the module setspytestmark = pytest.mark.parallel_threads_limit(4)). One failure is a segmentation fault insidecuMemPoolDestroy; the other is a data race on the test class instance. Both reproduce onmainitself, independent of the PR they were first noticed on.Failure 1: SEGV in
cuMemPoolDestroyfromtest_allocation_handle_forking_pickler_roundtripObserved on
mainfor the #2728 merge commitbcfbe72c8c7(run 34230002523, job 102076702071, CUDA 12.9.1 local, L4) and again on #2759 (run 34253228097, job 102163403217, CUDA 13.0.2 wheels, A100). The faulthandler dump is the same in both:Line 327 is the
mr.close()in the test'sfinally. Each of the four threads creates its own IPC-enabledDeviceMemoryResource, readsmr.allocation_handle, round-trips it throughmultiprocessing.reduction.ForkingPickler, closes the restored handle, and destroys its pool. The crash is inside the driver'scuMemPoolDestroywhile the other threads are exporting or destroying their own IPC pools. Whether this is a driver-level restriction on concurrent IPC pool export/destroy or a cuda.core teardown problem is not established; either way the test cannot run in parallel threads as written.Failure 2:
TestImportWrongMR.test_main[PinnedMR]pickles another thread's closed resourceObserved on #2759 (run 34253228097, job 102163403408, CUDA 13.3.0 local, L4). The test is marked
flaky(reruns=2)and failed all three attempts:ChildErrorHarness.test_mainstores its fixtures on the instance (self.device,self.mr,self._extra_mrs, andself.bufferset byPARENT_ACTION) and spawns the child withtarget=self.child_main, which picklesself. pytest-run-parallel runs the four threads against the same test instance and the same function-scopedipc_memory_resourcevalue, so one thread pickles aBufferwhose resource another thread has already closed. The same shared-state pattern applies to every subclass ofChildErrorHarnessin the file; this one just lost the race first.Suggested fix
ChildErrorHarnesssubclasses andtest_allocation_handle_forking_pickler_roundtrip@pytest.mark.thread_unsafe(reason: shared instance state andmultiprocessingspawn; concurrent IPC pool export/destroy), or drop the module-levelparallel_threads_limit(4)in favour of per-test marks.cuMemPoolDestroyof IPC-enabled pools from several threads is supposed to be safe; if it is, the SEGV is a cuda.core bug in pool teardown rather than a test-only issue.Environment
GitHub Actions, linux-aarch64, Python 3.14.7 free-threaded, cuda-bindings 13.x, pytest-run-parallel, CUDA 12.9.1 / 13.0.2 / 13.3.0.
Refs: #2728 (tests added), #2759 (where the failures were analysed).
@rluo8 and @seberg for viz