]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Issue 0020421: EDF 1071 GUI: Problem in the python console with numpy exceptions
authorvsr <vsr@opencascade.com>
Mon, 27 Jul 2009 10:53:09 +0000 (10:53 +0000)
committervsr <vsr@opencascade.com>
Mon, 27 Jul 2009 10:53:09 +0000 (10:53 +0000)
Integrate patch from EDF

src/PyConsole/PyConsole_Interp.cxx
src/PyInterp/PyInterp_Interp.cxx

index e915c185a3f84a3536e4cc4935945be162346dbb..b66f34d743786968e93fe43bce2964893b8344ca 100644 (file)
@@ -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
 */
index 3960bb8d9c405e8eee848f0e157b2c92c06e5a3e..0823e8657158e42c2606a068756bb14c15f23aa4 100644 (file)
 //  Module : SALOME
 //
 #include "PyInterp_Interp.h"  // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+#include <pythread.h>
 
 #include <cStringIO.h>
 #include <structmember.h>
 
 #include <string>
 #include <vector>
+#include <map>
 #include <iostream>
 
 #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<long,PyThreadState*> 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);
 }
 
 /*!