qMRMLSubjectHierarchyComboBox: Setting noneDisplay from Python segfaults

Hi,

I’m trying to write a SegmentEditorEffect to apply a mask to all volumes in a study (related to Applying manipulations to all volumes in a study ). I want the result to go into a study, so where MaskVolume has a volume-selection combobox, I’m trying to get a study-selection one. Naturally, this is an instance of qMRMLSubjectHierarchyComboBox. By default, I want it to be a new study, so I’m setting noneEnabled = True and trying to set noneDisplay to a string like “(Create a new study)”. This causes Slicer (5.8.1 on Linux) to segfault.

I’m saying that this was the problem, not only because commenting out that line “solved” the problem, but also because I ran Slicer under a gdb and got this where the SIGSEGV was received:

#0  0x00007ffff3701102 in QStandardItem::child(int, int) const () from .../Slicer-5.8.1-linux-amd64/bin/../lib/Slicer-5.8/libQt5Gui.so.5
#1  0x00007ffedcc3d360 in qMRMLSubjectHierarchyModel::setNoneDisplay(QString const&) ()
   from .../Slicer-5.8.1-linux-amd64/bin/../lib/Slicer-5.8/qt-loadable-modules/libqSlicerSubjectHierarchyModuleWidgets.so
#2  0x00007ffedcca3c5e in ?? () from .../Slicer-5.8.1-linux-amd64/bin/../lib/Slicer-5.8/qt-loadable-modules/libqSlicerSubjectHierarchyModuleWidgets.so
#3  0x00007ffedcca403b in qMRMLSubjectHierarchyComboBox::qt_metacall(QMetaObject::Call, int, void**) ()
   from .../Slicer-5.8.1-linux-amd64/bin/../lib/Slicer-5.8/qt-loadable-modules/libqSlicerSubjectHierarchyModuleWidgets.so
#4  0x00007ffff2cacad0 in QMetaProperty::write(QObject*, QVariant const&) const () from .../Slicer-5.8.1-linux-amd64/bin/../lib/Slicer-5.8/libQt5Core.so.5
#5  0x00007fffe37636cc in ?? () from .../Slicer/Slicer-5.8.1-linux-amd64/bin/../lib/Slicer-5.8/libPythonQt.so
#6  0x00007fffb71075df in PyObject_SetAttr () from .../Slicer-5.8.1-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#7  0x00007fffb70798e9 in _PyEval_EvalFrameDefault () from .../Slicer-5.8.1-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
#8  0x00007fffb71c0b37 in _PyEval_EvalCode () from .../Slicer-5.8.1-linux-amd64/bin/../lib/Python/lib/libpython3.9.so
...

Is this known? Has this code changed recently? I know 5.10.0 is just out, haven’t had a chance to play with it yet. I did search for related (open and closed) issues, and found none.

At least on Windows the following snippet appears to work for me with Slicer 5.8.1 and Slicer 5.10.0. It was also successfully when I tried Slicer 5.10.0 on macOS. Can you try this code snippet?
{DF5333E0-C3BA-45E5-A100-D085102D352F}

import SampleData
SampleData.SampleDataLogic().downloadMRHead()
subject_hierarchy_combobox = slicer.qMRMLSubjectHierarchyComboBox()
subject_hierarchy_combobox.setMRMLScene(slicer.mrmlScene)
subject_hierarchy_combobox.show()
subject_hierarchy_combobox.noneEnabled = True
subject_hierarchy_combobox.noneDisplay = "(Create a new study)"

Yes, that snippet works for me too (I tried also a variation without loading any data, which is more like how I saw the segfault).

I’ll try to create a reproduction I can share.

subject_hierarchy_combobox = slicer.qMRMLSubjectHierarchyComboBox()
# subject_hierarchy_combobox.setMRMLScene(slicer.mrmlScene)
subject_hierarchy_combobox.show()
subject_hierarchy_combobox.noneEnabled = True
subject_hierarchy_combobox.noneDisplay = "(Create a new study)"

This (setting the noneDisplay without/before setting the scene) segfaults.

This should fix it

I didn’t even build this because it seems so trivial but based on the call stack I’m pretty sure this fixes it. It makes sense that there is no scene item found in the combobox’s model if there is no scene set to it.

Thanks for the detailed report @shai-ikko !