File tree 1 file changed +18
-0
lines changed 1 file changed +18
-0
lines changed Original file line number Diff line number Diff line change @@ -113,6 +113,24 @@ mod raw {
113
113
#[ cfg( not( Py_3_14 ) ) ]
114
114
pub unsafe extern "C" fn PyGILState_Ensure ( ) -> PyGILState_STATE {
115
115
let guard = HangThread ;
116
+ // If `PyGILState_Ensure` calls `pthread_exit`, which it does on Python < 3.14
117
+ // when the interpreter is shutting down, this will cause a forced unwind.
118
+ // doing a forced unwind through a function with a Rust destructor is unspecified
119
+ // behavior.
120
+ //
121
+ // However, currently it runs the destructor, which will cause the thread to
122
+ // hang as it should.
123
+ //
124
+ // And if we don't catch the unwinding here, then one of our callers probably has a destructor,
125
+ // so it's unspecified behavior anyway, and on many configurations causes the process to abort.
126
+ //
127
+ // The alternative is for pyo3 to contain custom C or C++ code that catches the `pthread_exit`,
128
+ // but that's also annoying from a portability point of view.
129
+ //
130
+ // On Windows, `PyGILState_Ensure` calls `_endthreadex` instead, which AFAICT can't be caught
131
+ // and therefore will cause unsafety if there are pinned objects on the stack. AFAICT there's
132
+ // nothing we can do it other than waiting for Python 3.14 or not using Windows. At least,
133
+ // if there is nothing pinned on the stack, it won't cause the process to crash.
116
134
let ret: PyGILState_STATE = raw:: PyGILState_Ensure ( ) ;
117
135
std:: mem:: forget ( guard) ;
118
136
ret
You can’t perform that action at this time.
0 commit comments