[QGIS Commit] r15154 - branches/threading-branch/src/python

svn_qgis at osgeo.org svn_qgis at osgeo.org
Thu Feb 10 16:46:31 EST 2011


Author: wonder
Date: 2011-02-10 13:46:31 -0800 (Thu, 10 Feb 2011)
New Revision: 15154

Modified:
   branches/threading-branch/src/python/qgspythonutilsimpl.cpp
Log:
Hopefully solved the problems with Python and multithreading.

Solution: release GIL on startup, make sure that all our calls to Python API
acquire and then release GIL again (calls from SIP are safe, too).


Modified: branches/threading-branch/src/python/qgspythonutilsimpl.cpp
===================================================================
--- branches/threading-branch/src/python/qgspythonutilsimpl.cpp	2011-02-10 17:32:07 UTC (rev 15153)
+++ branches/threading-branch/src/python/qgspythonutilsimpl.cpp	2011-02-10 21:46:31 UTC (rev 15154)
@@ -35,6 +35,9 @@
 #include <QDir>
 
 
+PyThreadState* _mainState;
+
+
 QgsPythonUtilsImpl::QgsPythonUtilsImpl()
 {
   mMainModule = NULL;
@@ -51,6 +54,9 @@
   // initialize python
   Py_Initialize();
 
+  // initialize threading AND acquire GIL
+  PyEval_InitThreads();
+
   mPythonEnabled = true;
 
   mMainModule = PyImport_AddModule( "__main__" ); // borrowed reference
@@ -105,6 +111,13 @@
 
   // initialize 'iface' object
   runString( "qgis.utils.initInterface(" + QString::number(( unsigned long ) interface ) + ")" );
+
+  // release GIL!
+  // Later on, we acquire GIL just before doing some Python calls and
+  // release GIL again when the work with Python API is done.
+  // (i.e. there must be PyGILState_Ensure + PyGILState_Release pair
+  // around any calls to Python API, otherwise we may segfault!)
+  _mainState = PyEval_SaveThread();
 }
 
 void QgsPythonUtilsImpl::exitPython()
@@ -135,11 +148,18 @@
 
 bool QgsPythonUtilsImpl::runStringUnsafe( const QString& command, bool single )
 {
+  PyGILState_STATE gstate;
+  gstate = PyGILState_Ensure();
+
   // TODO: convert special characters from unicode strings u"..." to \uXXXX
   // so that they're not mangled to utf-8
   // (non-unicode strings can be mangled)
   PyRun_String( command.toUtf8().data(), single ? Py_single_input : Py_file_input, mMainDict, mMainDict );
-  return ( PyErr_Occurred() == 0 );
+  bool res = ( PyErr_Occurred() == 0 );
+
+PyGILState_Release( gstate );
+
+  return res;
 }
 
 bool QgsPythonUtilsImpl::runString( const QString& command, QString msgOnError )
@@ -180,6 +200,8 @@
 {
 #define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
 
+  PyGILState_STATE gstate;
+  gstate = PyGILState_Ensure();
 
   QString errMsg;
   QString result;
@@ -245,6 +267,8 @@
   Py_XDECREF( traceback );
   Py_XDECREF( type );
 
+  PyGILState_Release( gstate );
+
   return result;
 }
 
@@ -365,16 +389,20 @@
 
 bool QgsPythonUtilsImpl::evalString( const QString& command, QString& result )
 {
+  PyGILState_STATE gstate;
+  gstate = PyGILState_Ensure();
+
   PyObject* res = PyRun_String( command.toUtf8().data(), Py_eval_input, mMainDict, mMainDict );
+  bool success = ( res != NULL );
 
   // TODO: error handling
 
-  if ( res != NULL )
-  {
+  if ( success )
     result = PyObjectToQString( res );
-    return true;
-  }
-  return false;
+
+  PyGILState_Release( gstate );
+
+  return success;
 }
 
 



More information about the QGIS-commit mailing list