Skip to content

Commit a9165d6

Browse files
is_shutting_down
1 parent e06b299 commit a9165d6

5 files changed

Lines changed: 36 additions & 8 deletions

File tree

cuda_bindings/cuda/bindings/utils/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
3-
3+
import atexit
44
from typing import Any, Callable
55

66
from ._ptx_utils import get_minimal_required_cuda_ver_from_ptx_ver, get_ptx_ver

cuda_core/cuda/core/experimental/_event.pyx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ from cuda.core.experimental._utils.cuda_utils import (
1717
CUDAError,
1818
driver,
1919
handle_return,
20+
is_shutting_down
2021
)
2122

2223
if TYPE_CHECKING:
@@ -108,10 +109,11 @@ cdef class Event:
108109
self._ctx_handle = ctx_handle
109110
return self
110111

111-
cpdef close(self):
112+
cpdef close(self, is_shutting_down=is_shutting_down):
112113
"""Destroy the event."""
113114
if self._handle is not None:
114-
err, = driver.cuEventDestroy(self._handle)
115+
if not is_shutting_down()
116+
err, = driver.cuEventDestroy(self._handle)
115117
self._handle = None
116118
raise_if_driver_error(err)
117119

cuda_core/cuda/core/experimental/_memory.pyx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ from typing import TypeVar, Union
1515

1616
from cuda.core.experimental._dlpack import DLDeviceType, make_py_capsule
1717
from cuda.core.experimental._stream import Stream, default_stream
18-
from cuda.core.experimental._utils.cuda_utils import driver
18+
from cuda.core.experimental._utils.cuda_utils import driver, is_shutting_down
1919

2020
# TODO: define a memory property mixin class and make Buffer and
2121
# MemoryResource both inherit from it
@@ -59,7 +59,7 @@ cdef class Buffer:
5959
def __del__(self):
6060
self.close()
6161

62-
cpdef close(self, stream: Stream = None):
62+
cpdef close(self, stream: Stream = None, is_shutting_down=is_shutting_down):
6363
"""Deallocate this buffer asynchronously on the given stream.
6464
6565
This buffer is released back to their memory resource
@@ -72,7 +72,8 @@ cdef class Buffer:
7272
the behavior depends on the underlying memory resource.
7373
"""
7474
if self._ptr and self._mr is not None:
75-
self._mr.deallocate(self._ptr, self._size, stream)
75+
if not is_shutting_down():
76+
self._mr.deallocate(self._ptr, self._size, stream)
7677
self._ptr = 0
7778
self._mr = None
7879
self._ptr_obj = None

cuda_core/cuda/core/experimental/_stream.pyx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ from cuda.core.experimental._utils.cuda_utils import (
2525
driver,
2626
get_device_from_ctx,
2727
handle_return,
28+
is_shutting_down
2829
)
2930

3031

@@ -187,7 +188,7 @@ cdef class Stream:
187188
def __del__(self):
188189
self.close()
189190

190-
cpdef close(self):
191+
cpdef close(self, is_shutting_down=is_shutting_down):
191192
"""Destroy the stream.
192193
193194
Destroy the stream if we own it. Borrowed foreign stream
@@ -196,7 +197,8 @@ cdef class Stream:
196197
"""
197198
if self._owner is None:
198199
if self._handle and not self._builtin:
199-
handle_return(driver.cuStreamDestroy(self._handle))
200+
if not is_shutting_down():
201+
handle_return(driver.cuStreamDestroy(self._handle))
200202
else:
201203
self._owner = None
202204
self._handle = None

cuda_core/cuda/core/experimental/_utils/cuda_utils.pyx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

5+
import atexit
56
import functools
67
import importlib.metadata
78
from collections import namedtuple
@@ -222,3 +223,25 @@ def get_binding_version():
222223
except importlib.metadata.PackageNotFoundError:
223224
major_minor = importlib.metadata.version("cuda-python").split(".")[:2]
224225
return tuple(int(v) for v in major_minor)
226+
227+
# This code is to signal when the interpreter is in shutdown mode
228+
# to prevent using globals that could be already deleted in
229+
# objects `__del__` method
230+
#
231+
# This solution is taken from the Numba/llvmlite code
232+
_shutting_down = [False]
233+
234+
235+
@atexit.register
236+
def _at_shutdown():
237+
_shutting_down[0] = True
238+
239+
240+
def is_shutting_down(_shutting_down=_shutting_down):
241+
"""
242+
Whether the interpreter is currently shutting down.
243+
For use in finalizers, __del__ methods, and similar; it is advised
244+
to early bind this function rather than look it up when calling it,
245+
since at shutdown module globals may be cleared.
246+
"""
247+
return _shutting_down[0]

0 commit comments

Comments
 (0)