Extract centerline may crash slicer on tight arterial stenosis

First, this is reported for its technical aspects.

Centerline extraction may not always produce a good one with default parameters and only two endpoints. I noticed that by decreasing ‘Decimation aggressiveness’, centerline extraction ends up with good results very often.

My last extraction on a femoral segment with a long stenosis, very tight st some points, succeeded with default parameters, but crashed Slicer when ‘Decimation aggressiveness’ is decreased to 1.0 k (as an experiment). This is reproducible. The scene MRB file is linked here. And the backtrace follows :

Switch to module:  "ExtractCenterline"
Found CommandLine Module, target is  /data_ssd/programs/Slicer-4.13.0-2021-08-28-linux-amd64/bin/../lib/Slicer-4.13/cli-modules/Decimation
ModuleType: CommandLineModule
Decimation command line: 

/data_ssd/programs/Slicer-4.13.0-2021-08-28-linux-amd64/bin/../lib/Slicer-4.13/cli-modules/Decimation --reductionFactor 0.692497 --method FastQuadric --deleteBoundary --aggressiveness 1 /tmp/Slicer/GBCFIJ_vtkMRMLModelNodeF.obj /tmp/Slicer/GBCFIJ_vtkMRMLModelNodeG.obj 

Process 612589 stopped and restarted: thread 1 received signal: SIGCHLD
Decimation standard output:

Input: 16260 vertices,32520 triangles (target 10000)

Decimation standard error:

Unable to reduce mesh.



Decimation completed with errors



Input port 0 of algorithm vtkCleanPolyData(0x55555c430ab0) has 0 connections but is not optional.


No points to subdivide


<<Cannot triangulate; no input points


error: libstdc++.so.6 {0x00181389}: DIE has DW_AT_ranges(0x119c8) attribute, but range extraction failed (missing or invalid range list table), please file a bug and attach the file at the start of this error message
Process 612589 stopped
* thread #1, name = 'SlicerApp-real', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
    frame #0: 0x00007ffeff6da9a7 libvtkvmtkComputationalGeometry.so`vtkvmtkPolyDataCenterlines::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 535
libvtkvmtkComputationalGeometry.so`vtkvmtkPolyDataCenterlines::RequestData:
->  0x7ffeff6da9a7 <+535>: movq   (%rax), %rcx
    0x7ffeff6da9aa <+538>: movq   %rax, %rdi
    0x7ffeff6da9ad <+541>: callq  *0x190(%rcx)
    0x7ffeff6da9b3 <+547>: movq   (%rbp), %rcx
(lldb) bt
* thread #1, name = 'SlicerApp-real', stop reason = signal SIGSEGV: invalid address (fault address: 0x0)
  * frame #0: 0x00007ffeff6da9a7 libvtkvmtkComputationalGeometry.so`vtkvmtkPolyDataCenterlines::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) + 535
    frame #1: 0x00007fffe1911fdf libvtkCommon-9.0.so.1`vtkExecutive::CallAlgorithm(this=0x000055555f466ec0, request=0x000055555f463ce0, direction=<unavailable>, inInfo=0x000055555de7b750, outInfo=0x000055555da22cf0) at vtkExecutive.cxx:746:33
    frame #2: 0x00007fffe190d867 libvtkCommon-9.0.so.1`vtkDemandDrivenPipeline::ExecuteData(this=0x000055555f466ec0, request=0x000055555f463ce0, inInfo=0x000055555de7b750, outInfo=0x000055555da22cf0) at vtkDemandDrivenPipeline.cxx:462:22
    frame #3: 0x00007fffe1908a17 libvtkCommon-9.0.so.1`vtkCompositeDataPipeline::ExecuteData(this=0x000055555f466ec0, request=0x000055555f463ce0, inInfoVec=0x000055555de7b750, outInfoVec=0x000055555da22cf0) at vtkCompositeDataPipeline.cxx:161:32
    frame #4: 0x00007fffe190d083 libvtkCommon-9.0.so.1`vtkDemandDrivenPipeline::ProcessRequest(this=0x000055555f466ec0, request=0x000055555f463ce0, inInfoVec=0x000055555de7b750, outInfoVec=<unavailable>) at vtkDemandDrivenPipeline.cxx:261:22
    frame #5: 0x00007fffe1937b1a libvtkCommon-9.0.so.1`vtkStreamingDemandDrivenPipeline::ProcessRequest(this=0x000055555f466ec0, request=0x000055555f463ce0, inInfoVec=<unavailable>, outInfoVec=0x000055555da22cf0) at vtkStreamingDemandDrivenPipeline.cxx:0
    frame #6: 0x00007fffe190d635 libvtkCommon-9.0.so.1`vtkDemandDrivenPipeline::UpdateData(this=0x000055555f466ec0, outputPort=<unavailable>) at vtkDemandDrivenPipeline.cxx:419:16
    frame #7: 0x00007fffe19380d1 libvtkCommon-9.0.so.1`vtkStreamingDemandDrivenPipeline::Update(this=0x000055555f466ec0, port=0, requests=<unavailable>) at vtkStreamingDemandDrivenPipeline.cxx:417:34
    frame #8: 0x00007fff8c2d2b92 vtkCommonExecutionModel.cpython-36m-x86_64-linux-gnu.so`PyvtkAlgorithm_Update(_object*, _object*) [inlined] PyvtkAlgorithm_Update_s2(self=<unavailable>, args=<unavailable>) at vtkAlgorithmPython.cxx:2338:11
    frame #9: 0x00007fff8c2d2b29 vtkCommonExecutionModel.cpython-36m-x86_64-linux-gnu.so`PyvtkAlgorithm_Update(self=<unavailable>, args=<unavailable>) at vtkAlgorithmPython.cxx:2425
    frame #10: 0x00007fffe51b89fc libpython3.6m.so`_PyCFunction_FastCallDict(func_obj=0x00007ffef6f41ca8, args=0x000055555f1e0f98, nargs=<unavailable>, kwargs=0x0000000000000000) at methodobject.c:234:22
    frame #11: 0x00007fffe522d1bb libpython3.6m.so`call_function(pp_stack=0x00007fffffffae08, oparg=<unavailable>, kwnames=<unavailable>) at ceval.c:4837:9
    frame #12: 0x00007fffe522a43e libpython3.6m.so`_PyEval_EvalFrameDefault(f=0x000055555f1e0d68, throwflag=<unavailable>) at ceval.c:3335:19
    frame #13: 0x00007fffe522dd56 libpython3.6m.so`_PyEval_EvalCodeWithName [inlined] PyEval_EvalFrameEx(f=0x000055555f1e0d68, throwflag=0) at ceval.c:754:12
    frame #14: 0x00007fffe522dd40 libpython3.6m.so`_PyEval_EvalCodeWithName(_co=<unavailable>, globals=<unavailable>, locals=<unavailable>, args=0x000055555e182d68, argcount=<unavailable>, kwnames=0x0000000000000000, kwargs=0x000055555e182d88, kwcount=0, kwstep=1, defs=0x00007fff105f86f0, defcount=1, kwdefs=0x0000000000000000, closure=0x0000000000000000, name=0x00007fff105ff5d0, qualname=0x00007fff105812d0) at ceval.c:4166
    frame #15: 0x00007fffe522e41c libpython3.6m.so`fast_function(func=<unavailable>, stack=0x000055555e182d68, nargs=<unavailable>, kwnames=<unavailable>) at ceval.c:4978:12
    frame #16: 0x00007fffe522d194 libpython3.6m.so`call_function(pp_stack=0x00007fffffffb0a8, oparg=<unavailable>, kwnames=<unavailable>) at ceval.c:4858:17
    frame #17: 0x00007fffe522a43e libpython3.6m.so`_PyEval_EvalFrameDefault(f=0x000055555e182b38, throwflag=<unavailable>) at ceval.c:3335:19
    frame #18: 0x00007fffe522e887 libpython3.6m.so`_PyFunction_FastCallDict(func=<unavailable>, args=<unavailable>, nargs=<unavailable>, kwargs=<unavailable>) at ceval.c:0
    frame #19: 0x00007fffe5176612 libpython3.6m.so`_PyObject_FastCallDict(func=0x00007fff1058a158, args=0x00007fffffffb210, nargs=1, kwargs=0x0000000000000000) at abstract.c:2310:18
    frame #20: 0x00007fffe51767b1 libpython3.6m.so`_PyObject_Call_Prepend(func=0x00007fff1058a158, obj=0x00007ffe1412eb70, args=<unavailable>, kwargs=0x0000000000000000) at abstract.c:2373:14
    frame #21: 0x00007fffe51766b4 libpython3.6m.so`_PyObject_FastCallDict(func=0x00007ffe14152248, args=0x0000000000000000, nargs=0, kwargs=0x0000000000000000) at abstract.c:2331:18
    frame #22: 0x00007fffec2b7ecb libPythonQt.so`PythonQtSignalTarget::call(callable=0x00007ffe14152248, methodInfos=0x000055555c080110, arguments=0x00007fffffffb450, skipFirstArgumentOfMethodInfo=<unavailable>) at PythonQtSignalReceiver.cpp:130:14
    frame #23: 0x00007fffec2b8901 libPythonQt.so`PythonQtSignalReceiver::qt_metacall(QMetaObject::Call, int, void**) [inlined] PythonQtSignalTarget::call(this=0x000055555d4c51e0, arguments=0x00007fffffffb450) const at PythonQtSignalReceiver.cpp:56:22
    frame #24: 0x00007fffec2b88e9 libPythonQt.so`PythonQtSignalReceiver::qt_metacall(this=0x000055555bed1e00, c=<unavailable>, id=5, arguments=<unavailable>) at PythonQtSignalReceiver.cpp:273
    frame #25: 0x00007ffff62f14a7 libQt5Core.so.5`___lldb_unnamed_symbol4768$$libQt5Core.so.5 + 631
    frame #26: 0x00007ffff6e864e3 libQt5Widgets.so.5`QAbstractButton::clicked(bool) + 67
    frame #27: 0x00007ffff6e8676c libQt5Widgets.so.5`___lldb_unnamed_symbol1438$$libQt5Widgets.so.5 + 60
    frame #28: 0x00007ffff6e88374 libQt5Widgets.so.5`___lldb_unnamed_symbol1444$$libQt5Widgets.so.5 + 196
    frame #29: 0x00007ffff6e88595 libQt5Widgets.so.5`QAbstractButton::mouseReleaseEvent(QMouseEvent*) + 245
    frame #30: 0x00007ffff6dd20be libQt5Widgets.so.5`QWidget::event(QEvent*) + 526
    frame #31: 0x00007ffff6d8ed62 libQt5Widgets.so.5`QApplicationPrivate::notify_helper(QObject*, QEvent*) + 130
    frame #32: 0x00007ffff6d96ac9 libQt5Widgets.so.5`QApplication::notify(QObject*, QEvent*) + 2729
    frame #33: 0x00007ffff7c8cd1e libqSlicerBaseQTGUI.so`qSlicerApplication::notify(this=<unavailable>, receiver=<unavailable>, event=<unavailable>) at qSlicerApplication.cxx:412:26
    frame #34: 0x00007ffff62ba3aa libQt5Core.so.5`QCoreApplication::notifyInternal2(QObject*, QEvent*) + 314
    frame #35: 0x00007ffff6d9557b libQt5Widgets.so.5`QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) + 443
    frame #36: 0x00007ffff6deba84 libQt5Widgets.so.5`___lldb_unnamed_symbol921$$libQt5Widgets.so.5 + 740
    frame #37: 0x00007ffff6deedb5 libQt5Widgets.so.5`___lldb_unnamed_symbol932$$libQt5Widgets.so.5 + 517
    frame #38: 0x00007ffff6d8ed62 libQt5Widgets.so.5`QApplicationPrivate::notify_helper(QObject*, QEvent*) + 130
    frame #39: 0x00007ffff7c8cd1e libqSlicerBaseQTGUI.so`qSlicerApplication::notify(this=<unavailable>, receiver=<unavailable>, event=<unavailable>) at qSlicerApplication.cxx:412:26
    frame #40: 0x00007ffff62ba3aa libQt5Core.so.5`QCoreApplication::notifyInternal2(QObject*, QEvent*) + 314
    frame #41: 0x00007ffff6693210 libQt5Gui.so.5`QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) + 1712
    frame #42: 0x00007ffff66687e5 libQt5Gui.so.5`QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 181
    frame #43: 0x00007fffce0d1fcc libQt5XcbQpa.so.5`___lldb_unnamed_symbol407$$libQt5XcbQpa.so.5 + 28
    frame #44: 0x00007fffe071b10c libglib-2.0.so.0`g_main_context_dispatch + 620
    frame #45: 0x00007fffe076eba9 libglib-2.0.so.0`___lldb_unnamed_symbol449$$libglib-2.0.so.0 + 521
    frame #46: 0x00007fffe0718871 libglib-2.0.so.0`g_main_context_iteration + 49
    frame #47: 0x00007ffff6312fd6 libQt5Core.so.5`QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 102
    frame #48: 0x00007ffff62b8d1c libQt5Core.so.5`QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 300
    frame #49: 0x00007ffff62c1284 libQt5Core.so.5`QCoreApplication::exec() + 148
    frame #50: 0x00007ffff74e4436 libqSlicerBaseQTCore.so`qSlicerCoreApplication::exec() at qSlicerCoreApplication.cxx:876:19
    frame #51: 0x000055555555996c SlicerApp-real`main [inlined] (anonymous namespace)::SlicerAppMain(argc=1, argv=0x00007fffffffc2a8) at Main.cxx:62:10
    frame #52: 0x0000555555559781 SlicerApp-real`main(argc=<unavailable>, argv=0x00007fffffffc2a8) at qSlicerApplicationMainWrapper.cxx:56
    frame #53: 0x00007fffe1150b25 libc.so.6`__libc_start_main + 213
    frame #54: 0x000055555555968e SlicerApp-real`_start + 46
(lldb)

I further tried with a ‘Decimation aggressiveness’ value of 0.1 k in another segment of an aortic aneurysm (big tube, in contrast to a tight stenosis). It succeeded.

That is not a clinical issue as treatment options are quite clear in that case.

I just wish to report it so that a decimation failure could be managed, so as to avoid application crash. I can’t know if it’s up to ‘Extract centerline’ to handle this, or to the VMTK libs themselves.

Regards.

Thanks for reporting this. Since it is not a nominal use case and there is a workaround, we will not immediately address this. Also, the issue is most likely due to some missing null-pointer check in VTK and will be resolved in future VTK versions. But it is good to know about and track this issue, so it would be great if you could submit this as an issue to SlicerVMTK bugtracker.

Of course this can wait.
Submitted here.

1 Like