Use of qt.Signal leads to a crash on exit

Recently, I have been investigating the source of a crash on exit.

To reproduce the crash:

./Slicer --no-main-window --testing

Notes:

  • removing the connection to the closed signal object here in the DICOM module avoids the crash on exit from happening.
  • disconnecting the signal on exit (or just after setting the connection) does not prevent the crash from happening
  • starting the application with the main window prevents the crash on exit from happening
  • a possibly related thread on the PythonQt forum is this one: Segmentation fault after emiting a signal
  • yesterday, we updated (see r28485) to use the latest version of PythonQt thinking the issue would be addressed … but it is not.

Create a script test.py with the following content:

class FooDetailsWidget(qt.QWidget):
  closed = qt.Signal() # Invoked when the dicom widget is closed using the close method
  def __init__(self):
    qt.QWidget.__init__(self)

class Foo(object):
  def __init__(self):
    self.detailsPopup = FooDetailsWidget()
    self.detailsPopup.closed.connect(self.onDetailsPopupClosed)
  def onDetailsPopupClosed(self):
    print("onDetailsPopupClosed")

d = Foo()
d.detailsPopup.closed.emit()

# In this case, disconnecting prevent the crash on exit from happening
# d.detailsPopup.closed.disconnect(d.onDetailsPopupClosed)

and running Slicer with the following allows to reproduce a crash on exit. But:

  • the condition are not exactly the same
  • disconnecting the signal prevent the crash from happening whereas in the DICOM module it does not
  • with/without --no-main-window lead to a crash
./Slicer --disable-modules --no-main-window --testing --python-script /tmp/test.py