File tree Expand file tree Collapse file tree 2 files changed +21
-13
lines changed
Expand file tree Collapse file tree 2 files changed +21
-13
lines changed Original file line number Diff line number Diff line change @@ -149,6 +149,23 @@ mod doctest {
149149#[ inline( always) ]
150150fn cold ( ) { }
151151
152+ /// An RAII guard for avoiding deadlocks with the GIL or other global
153+ /// synchronization events in the Python runtime
154+ // FIXME create a proper MutexExt trait that handles poisoning and upstream to PyO3
155+ struct ThreadStateGuard ( * mut pyo3:: ffi:: PyThreadState ) ;
156+
157+ impl ThreadStateGuard {
158+ fn new ( ) -> ThreadStateGuard {
159+ ThreadStateGuard ( unsafe { pyo3:: ffi:: PyEval_SaveThread ( ) } )
160+ }
161+ }
162+
163+ impl Drop for ThreadStateGuard {
164+ fn drop ( & mut self ) {
165+ unsafe { pyo3:: ffi:: PyEval_RestoreThread ( self . 0 ) } ;
166+ }
167+ }
168+
152169/// Create a [`PyArray`] with one, two or three dimensions.
153170///
154171/// This macro is backed by [`ndarray::array`].
Original file line number Diff line number Diff line change @@ -19,6 +19,7 @@ use rustc_hash::FxHashMap;
1919use crate :: dtype:: { clone_methods_impl, Element , PyArrayDescr , PyArrayDescrMethods } ;
2020use crate :: npyffi:: PyDataType_SET_ELSIZE ;
2121use crate :: npyffi:: NPY_TYPES ;
22+ use crate :: ThreadStateGuard ;
2223
2324/// A newtype wrapper around [`[u8; N]`][Py_UCS1] to handle [`byte` scalars][numpy-bytes] while satisfying coherence.
2425///
@@ -178,22 +179,12 @@ impl TypeDescriptors {
178179 byteorder : c_char ,
179180 size : usize ,
180181 ) -> Bound < ' py , PyArrayDescr > {
181- // FIXME create a proper MutexExt trait that handles poisoning and upstream to PyO3
182- struct Guard ( * mut pyo3:: ffi:: PyThreadState ) ;
183-
184- impl Drop for Guard {
185- fn drop ( & mut self ) {
186- unsafe { pyo3:: ffi:: PyEval_RestoreThread ( self . 0 ) } ;
187- }
188- }
189-
190- // we are currently attached to the python runtime and we might block trying to acquire
191- // the dtype cache mutex, so detach to avoid a possible deadlock.
192- let ts_guard = Guard ( unsafe { pyo3:: ffi:: PyEval_SaveThread ( ) } ) ;
182+ // Detach from the runtime to avoid deadlocking on acquiring the mutex.
183+ let ts_guard = ThreadStateGuard :: new ( ) ;
193184
194185 let mut dtypes = self . dtypes . lock ( ) . expect ( "dtype cache poisoned" ) ;
195186
196- // we've acquire the dtype cache lock so it's safe to re-attach to the runtime
187+ // Now we hold the mutex so it's safe to re-attach to the runtime.
197188 drop ( ts_guard) ;
198189
199190 let dtype = match dtypes. get_or_insert_with ( Default :: default) . entry ( size) {
You can’t perform that action at this time.
0 commit comments