[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