]> 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 11:06:21 +0000 (11:06 +0000)
committervsr <vsr@opencascade.com>
Mon, 27 Jul 2009 11:06:21 +0000 (11:06 +0000)
Integrate patch from EDF

src/PyInterp/PyInterp_base.cxx
src/PythonConsole/PythonConsole_PyInterp.cxx

index 6fdad34eda0dd95ac7a026bde6b8b851768579cc..8ff5f9e102fed7162e6ca928d47c7ba975f5992c 100644 (file)
 #include <vector>
 
 #include "PyInterp_base.h" // this include must be first (see PyInterp_base.h)!
+#include <pythread.h>
 #include <cStringIO.h>
 #include <structmember.h>
+#include <map>
 
-using namespace std;
+// 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;
 
 PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): 
   myThreadState(theThreadState),
@@ -62,7 +65,8 @@ PyLockWrapper::~PyLockWrapper()
 #endif
 }
 
-class PyReleaseLock{
+class PyReleaseLock
+{
 public:
   ~PyReleaseLock(){
     PyEval_ReleaseLock();
@@ -70,8 +74,41 @@ public:
 };
 
 
-PyLockWrapper PyInterp_base::GetLockWrapper(){
-  return _tstate;
+PyLockWrapper PyInterp_base::GetLockWrapper()
+{
+  if (_tstate->interp == PyInterp_base::_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;
 }
 
 static void
@@ -217,7 +254,7 @@ void PyInterp_base::initialize()
 
   initState();
 
-  PyLockWrapper aLock= GetLockWrapper();
+  PyEval_AcquireThread(_tstate);
 
   initContext();
 
@@ -225,6 +262,7 @@ void PyInterp_base::initialize()
   PyObjWrapper m(PyImport_ImportModule("codeop"));
   if(!m){
     PyErr_Print();
+    PyEval_ReleaseThread(_tstate);
     return;
   }
 
@@ -234,6 +272,7 @@ void PyInterp_base::initialize()
 
   // All the initRun outputs are redirected to the standard output (console)
   initRun();
+  PyEval_ReleaseThread(_tstate);
 }
 
 void PyInterp_base::init_python()
@@ -255,11 +294,11 @@ void PyInterp_base::init_python()
   _gtstate = PyEval_SaveThread(); // Release global thread state
 }
 
-string PyInterp_base::getbanner()
+std::string PyInterp_base::getbanner()
 {
  // Should we take the lock ?
  // PyEval_RestoreThread(_tstate);
-  string aBanner("Python ");
+  std::string aBanner("Python ");
   aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
   aBanner = aBanner + "\ntype help to get general information on environment\n";
   //PyEval_SaveThread();
index 878ef9d49b47248b74cfd5c8b57cb6cb4ad83fa6..b6c9d0dd58f723927ad4e2bfa4339311107ca8df 100755 (executable)
@@ -69,32 +69,14 @@ PythonConsole_PyInterp::~PythonConsole_PyInterp()
  * but if we have copied some modules and imported others problems may arise with operations that
  * are not allowed in restricted execution environment. So we must impose that all interpreters
  * have identical __builtin__ module.
- * That's all, for the moment ...
+ *
+ * When calling initState the GIL is not held
+ * It must not be held on exit
+ *
  */
 
 bool PythonConsole_PyInterp::initState()
 {
-  /*
-   * The GIL is acquired on input and released on output
-   */
-    /*PyEval_AcquireLock();
-#ifdef WNT 
-  _tstate = PyGILState_GetThisThreadState();
-  // if no thread state defined
-  if ( _tstate )
-    PyThreadState_Swap(_tstate);
-  else
-#endif
-  {
-    _tstate = Py_NewInterpreter(); // create an interpreter and save current state
-    PySys_SetArgv(PyInterp_base::_argc,PyInterp_base::_argv); // initialize sys.argv
-    //if(MYDEBUG) MESSAGE("PythonConsole_PyInterp::initState - this = "<<this<<"; _tstate = "<<_tstate);
-  }*/
-
-  /*
-   * 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
@@ -131,8 +113,8 @@ bool PythonConsole_PyInterp::initState()
 
 /*!
    The GIL is assumed to be held
-   It is the caller responsability caller to acquire the GIL
-   It will still be held on initContext output
+   It is the caller responsability to acquire the GIL.
+   It must still be held on initContext() exit.
 */
 bool PythonConsole_PyInterp::initContext()
 {