From 4a5592e6940da9546c45c8eec46874acd64d8750 Mon Sep 17 00:00:00 2001 From: vsr Date: Mon, 27 Jul 2009 10:53:09 +0000 Subject: [PATCH] Issue 0020421: EDF 1071 GUI: Problem in the python console with numpy exceptions Integrate patch from EDF --- src/PyConsole/PyConsole_Interp.cxx | 10 ++++--- src/PyInterp/PyInterp_Interp.cxx | 45 ++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/PyConsole/PyConsole_Interp.cxx b/src/PyConsole/PyConsole_Interp.cxx index e915c185a..b66f34d74 100644 --- a/src/PyConsole/PyConsole_Interp.cxx +++ b/src/PyConsole/PyConsole_Interp.cxx @@ -84,12 +84,14 @@ PyConsole_Interp::~PyConsole_Interp() /*! \brief Initialize internal Python interpreter state. + + When calling initState the GIL is not held + It must not be held on exit + \return \c true on success */ bool PyConsole_Interp::initState() { - // The GIL is acquired and will be held on initState output - // It is the caller responsability to release the lock if needed PyEval_AcquireLock(); _tstate = Py_NewInterpreter(); // create an interpreter and save current state PySys_SetArgv(PyInterp_Interp::_argc,PyInterp_Interp::_argv); // initialize sys.argv @@ -120,8 +122,8 @@ bool PyConsole_Interp::initState() \brief Initialize python interpeter context. The GIL is assumed to be held. - It is the caller responsability caller to acquire the GIL. - It will still be held on initContext() exit. + It is the caller responsability to acquire the GIL. + It must still be held on initContext() exit. \return \c true on success */ diff --git a/src/PyInterp/PyInterp_Interp.cxx b/src/PyInterp/PyInterp_Interp.cxx index 3960bb8d9..0823e8657 100644 --- a/src/PyInterp/PyInterp_Interp.cxx +++ b/src/PyInterp/PyInterp_Interp.cxx @@ -24,17 +24,22 @@ // Module : SALOME // #include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!! +#include #include #include #include #include +#include #include #define TOP_HISTORY_PY "--- top of history ---" #define BEGIN_HISTORY_PY "--- begin of history ---" +// a map to store python thread states that have been created for a given system thread (key=thread id,value=thread state) +std::map currentThreadMap; + /*! \class PyLockWrapper \brief Python GIL wrapper. @@ -55,7 +60,7 @@ PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): } /*! - \brief Desstructor. Automatically releases GIL. + \brief Destructor. Automatically releases GIL. */ PyLockWrapper::~PyLockWrapper() { @@ -71,7 +76,39 @@ PyLockWrapper::~PyLockWrapper() */ PyLockWrapper PyInterp_Interp::GetLockWrapper() { - return _tstate; + if (_tstate->interp == PyInterp_Interp::_interp) + return _tstate; + + // If we are here, we have a secondary python interpreter. Try to get a thread state synchronized with the system thread + long currentThreadid=PyThread_get_thread_ident(); // the system thread id + PyThreadState* theThreadState; + if(currentThreadMap.count(currentThreadid) != 0) + { + //a thread state exists for this thread id + PyThreadState* oldThreadState=currentThreadMap[currentThreadid]; + if(_tstate->interp ==oldThreadState->interp) + { + //The old thread state has the same python interpreter as this one : reuse the threadstate + theThreadState=oldThreadState; + } + else + { + //The old thread state has not the same python interpreter as this one : delete the old threadstate and create a new one + PyEval_AcquireLock(); + PyThreadState_Clear(oldThreadState); + PyThreadState_Delete(oldThreadState); + PyEval_ReleaseLock(); + theThreadState=PyThreadState_New(_tstate->interp); + currentThreadMap[currentThreadid]=theThreadState; + } + } + else + { + // no old thread state for this thread id : create a new one + theThreadState=PyThreadState_New(_tstate->interp); + currentThreadMap[currentThreadid]=theThreadState; + } + return theThreadState; } /* @@ -230,7 +267,7 @@ void PyInterp_Interp::initialize() initState(); - PyLockWrapper aLock = GetLockWrapper(); + PyEval_AcquireThread(_tstate); initContext(); @@ -238,6 +275,7 @@ void PyInterp_Interp::initialize() PyObjWrapper m(PyImport_ImportModule("codeop")); if(!m) { PyErr_Print(); + PyEval_ReleaseThread(_tstate); return; } @@ -247,6 +285,7 @@ void PyInterp_Interp::initialize() // All the initRun outputs are redirected to the standard output (console) initRun(); + PyEval_ReleaseThread(_tstate); } /*! -- 2.39.2