<div dir="ltr">Currently, if an observer is added in a python thread and then executed in another thread after the first one has finished, it will cause a segfault/access violation in the python interpreter.<div><br></div><div>This code reproduces the problem:</div><div><br></div><div><div><span style="font-family:monospace,monospace">    from Queue import Queue</span><br></div><div><font face="monospace, monospace">    from threading import Thread</font></div><div><font face="monospace, monospace">    import vtk</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    def on_delete(caller, event):</font></div><div><font face="monospace, monospace">        print 'on_delete:'</font></div><div><font face="monospace, monospace">        print '    caller:', caller</font></div><div><font face="monospace, monospace">        print '    event:', event</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    def create_object_with_observer(result_queue):</font></div><div><font face="monospace, monospace">        object_with_observer = vtk.vtkObject()</font></div><div><font face="monospace, monospace">        object_with_observer.AddObserver('DeleteEvent', on_delete)</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">        result_queue.put(object_with_observer)</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    def test_observer_command_with_threads():</font></div><div><font face="monospace, monospace">        result_queue = Queue()</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">        thread = Thread(target=create_object_with_observer, args=(result_queue,))</font></div><div><font face="monospace, monospace">        thread.start()</font></div><div><font face="monospace, monospace">        thread.join()</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">        object_with_observer = result_queue.get(block=True)</font></div><div><font face="monospace, monospace">        print object_with_observer</font></div><div><font face="monospace, monospace">        del object_with_observer  # <-- crashes here (would crash later without del too)</font></div><div><font face="monospace, monospace">        print 'checkpoint'</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    if __name__ == '__main__':</font></div><div><font face="monospace, monospace">        test_observer_command_with_threads()</font></div></div><div><br></div><div><br></div><div>This seems to happen because of this line in vtkPythonCommand.cxx, which seems to be assigning a bad ThreadState pointer to _PyThreadState_Current:</div><div><br></div><div><div><font face="monospace, monospace">    prevThreadState = PyThreadState_Swap(this->ThreadState);</font></div></div><div><br></div><div>(The pointer seems to be dangling. Perhaps vtkPythonCommand::SetThreadState should <i>incref </i>the PyThreadState* object?)<br></div><div><br></div><div>This bug is directly affecting dataset_adapter, because it causes a crash in this use case (dataset_adapter uses a command to store the numpy array ref):</div><div><br></div><div><div><span style="font-family:monospace,monospace">    from Queue import Queue</span><br></div><div><font face="monospace, monospace">    from threading import Thread</font></div><div><font face="monospace, monospace">    from vtk.numpy_interface.dataset_adapter import UnstructuredGrid</font></div><div><font face="monospace, monospace">    import numpy</font></div><div><font face="monospace, monospace">    import vtk</font></div><div><span style="font-family:monospace,monospace">    </span><br></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    def create_unstructured_grid(result_queue):</font></div><div><font face="monospace, monospace">        points = numpy.array([[0.0, 0.0, 0.0]])</font></div><div><font face="monospace, monospace">        ug = UnstructuredGrid(vtk.vtkUnstructuredGrid())</font></div><div><font face="monospace, monospace">        ug.SetPoints(points)</font></div><div><font face="monospace, monospace">        result_queue.put(ug)</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    def test_unstructured_grid_in_thread():</font></div><div><font face="monospace, monospace">        result_queue = Queue()</font></div><div><font face="monospace, monospace">        thread = Thread(target=create_unstructured_grid, args=(result_queue,))</font></div><div><font face="monospace, monospace">        thread.start()</font></div><div><font face="monospace, monospace">        thread.join()</font></div><div><font face="monospace, monospace">        ug = result_queue.get(block=True)</font></div><div><font face="monospace, monospace">        print ug</font></div><div><font face="monospace, monospace">        del ug  # <-- crashes</font></div><div><font face="monospace, monospace">        print 'checkpoint'</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    if __name__ == '__main__':</font></div><div><font face="monospace, monospace">        test_unstructured_grid_in_thread()</font></div></div><div><br></div><div><br></div><div>( I've already submitted a bug report here: <a href="http://www.paraview.org/Bug/view.php?id=15545">http://www.paraview.org/Bug/view.php?id=15545</a> )</div><div><br></div><div><br></div><div>  Best regards,</div><div>  Edson</div><div><br></div></div>