Index: Common/vtkPythonUtil.cxx =================================================================== RCS file: /vtk/cvsroot/VTK/Common/vtkPythonUtil.cxx,v retrieving revision 1.70 diff -u -r1.70 vtkPythonUtil.cxx --- Common/vtkPythonUtil.cxx 15 Dec 2004 14:35:03 -0000 1.70 +++ Common/vtkPythonUtil.cxx 17 Jun 2005 08:20:13 -0000 @@ -1730,6 +1730,10 @@ vtkPythonCommand::vtkPythonCommand() { this->obj = NULL; +#ifdef WITH_THREAD + // get ThreadState for the thread running this observer + this->ThreadState = PyThreadState_Get(); +#endif } vtkPythonCommand::~vtkPythonCommand() @@ -1739,6 +1743,9 @@ Py_DECREF(this->obj); } this->obj = NULL; +#ifdef WITH_THREAD + this->ThreadState = NULL; +#endif } void vtkPythonCommand::SetObject(PyObject *o) @@ -1749,6 +1756,16 @@ void vtkPythonCommand::Execute(vtkObject *ptr, unsigned long eventtype, void *CallData) { +#ifdef WITH_THREAD + // By definition, this method will be called from a running VTK method. + // The VTK wrapping code now gives up the GIL before calling VTK methods, + // so we have to reclaim it here before we can make any Python API calls. + // 1. first acquire the GIL + PyEval_AcquireLock(); + // 2. then swap in the thread state of this observer + PyThreadState_Swap(this->ThreadState); +#endif + PyObject *arglist, *result, *obj2; const char *eventname; @@ -1845,6 +1862,16 @@ } PyErr_Print(); } + +#ifdef WITH_THREAD + // We're returning to the VTK method, so we have to give up the GIL + // again. Other Python threads will be able to execute. + // 1. swap out thread state of this observer + PyThreadState_Swap(NULL); + // 2. give the lock back so other Python threads can execute again + PyEval_ReleaseLock(); +#endif + } //-------------------------------------------------------------------- Index: Common/vtkPythonUtil.h =================================================================== RCS file: /vtk/cvsroot/VTK/Common/vtkPythonUtil.h,v retrieving revision 1.33 diff -u -r1.33 vtkPythonUtil.h --- Common/vtkPythonUtil.h 17 Feb 2004 15:31:24 -0000 1.33 +++ Common/vtkPythonUtil.h 17 Jun 2005 08:20:13 -0000 @@ -167,6 +167,10 @@ void Execute(vtkObject *ptr, unsigned long eventtype, void *CallData); PyObject *obj; +#ifdef WITH_THREAD + PyThreadState *ThreadState; +#endif + protected: vtkPythonCommand(); ~vtkPythonCommand(); Index: Wrapping/vtkWrapPython.c =================================================================== RCS file: /vtk/cvsroot/VTK/Wrapping/vtkWrapPython.c,v retrieving revision 1.71 diff -u -r1.71 vtkWrapPython.c --- Wrapping/vtkWrapPython.c 4 Jan 2005 21:47:48 -0000 1.71 +++ Wrapping/vtkWrapPython.c 17 Jun 2005 08:20:15 -0000 @@ -739,7 +739,12 @@ fprintf(fp," else {\n"); sprintf(methodname,"op->%s",currentFunction->Name); } - + + // Release GIL right before we call potentially long-running code + // but AFTER all Python API calls. If we don't do this, no other + // Python thread can execute while VTK is processing. + fprintf(fp," Py_BEGIN_ALLOW_THREADS\n"); + switch (currentFunction->ReturnType%1000) { case 2: @@ -773,6 +778,10 @@ } } fprintf(fp,");\n"); + + // get GIL back right after call to long-running VTK code but + // BEFORE any calls to Python code + fprintf(fp," Py_END_ALLOW_THREADS\n"); if (currentFunction->NumberOfArguments == 1 && currentFunction->ArgTypes[0] == 5000)