diff options
Diffstat (limited to 'pyuno/source/module/pyuno_runtime.cxx')
-rw-r--r-- | pyuno/source/module/pyuno_runtime.cxx | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/pyuno/source/module/pyuno_runtime.cxx b/pyuno/source/module/pyuno_runtime.cxx index 62b3861288c3..5fa923c236dc 100644 --- a/pyuno/source/module/pyuno_runtime.cxx +++ b/pyuno/source/module/pyuno_runtime.cxx @@ -974,8 +974,21 @@ Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, PyThreadAttach::PyThreadAttach( PyInterpreterState *interp) + : m_isNewState(false) { - tstate = PyThreadState_New( interp ); + // note: *may* be called recursively, with PyThreadDetach between - in + // that case, don't create *new* PyThreadState but reuse! +#ifndef NDEBUG + PyThreadState const*const current = _PyThreadState_UncheckedGet(); + // dereference isn't safe but let's hope it's tolerable for debugging purpose + assert((current == nullptr || current->thread_id != PyThread_get_thread_ident()) && "recursive PyThreadAttach"); +#endif + tstate = PyGILState_GetThisThreadState(); // from TLS, possibly detached + if (!tstate) + { + m_isNewState = true; + tstate = PyThreadState_New( interp ); + } if( !tstate ) throw RuntimeException( "Couldn't create a pythreadstate" ); PyEval_AcquireThread( tstate); @@ -983,9 +996,19 @@ PyThreadAttach::PyThreadAttach( PyInterpreterState *interp) PyThreadAttach::~PyThreadAttach() { - PyThreadState_Clear( tstate ); - PyEval_ReleaseThread( tstate ); - PyThreadState_Delete( tstate ); + if (m_isNewState) + { // Clear needs GIL! + PyThreadState_Clear( tstate ); + } + if (m_isNewState) + { // note: PyThreadState_Delete(tstate) cannot be called, it will assert + // because it requires a PyThreadState to be set, but not the tstate! + PyThreadState_DeleteCurrent(); + } + else + { + PyEval_ReleaseThread( tstate ); + } } PyThreadDetach::PyThreadDetach() |