openigtlink / SlicerOpenIGTLink

OpenIGTLinkIF module as an Slicer Extension
Other
17 stars 28 forks source link

TDATA from Brainlab crashes 3D Slicer #128

Closed tokjun closed 11 months ago

tokjun commented 1 year ago

3D Slicer crashed after connecting to Brainlab via OpenIGTLink and clicking the "Start" button on the OpenIGTLink Remote module.

tokjun commented 1 year ago

Slicer crashes when it receives an RTS_TDATA message. The problem can be reproduced using a modified TrackingDataServer example, which sends an RTS_TDATA message when the client requests to stop tracking. The modified example is available under the test_rts_tdata branch in my repo

To build and start the modified TrackingData

$ git clone -b test_rts_tdata https://github.com/tokjun/OpenIGTLink.git
$ mkdir OpenIGTLink-build
$ cd OpenIGTLink-build
$ cmake -DBUILD_EXAMPLES:BOOL=TRUE ../OpenIGTLink
$ cd bin
$ ./TrackingDataServer 18944

Once the server has started, open 3D Slicer (SlicerOpenIGTLink module must be installed), and open IGT->OpenIGTLink. Create a client connector node, and connect to localhost:18944. If the connector becomes active successfully, open the IGT->OpenIGTLink Remote, choose the created connector node, click Start, and then click Stop. At this point, Slicer sends a STP_TDATA message to the server. In response, the server stops tracking and sends back an RTS_TDATA message, which causes a Slicer crash.

tokjun commented 12 months ago

Here's the backtrace (the line numbers might be different from the current version):

Thread 1 "SlicerApp-real" received signal SIGSEGV, Segmentation fault.
0x00007fff7c53c94c in igtl::MessageBase::UnpackBody (this=0x55555bf92350, crccheck=1, r=@0x7fffffffd0a4: 0) at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink-build/OpenIGTLink/Source/igtlMessageBase.cxx:906
(gdb) bt
#0  0x00007fff7c53c94c in igtl::MessageBase::UnpackBody(int, int&) (this=0x55555bf92350, crccheck=1, r=@0x7fffffffd0a4: 0)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink-build/OpenIGTLink/Source/igtlMessageBase.cxx:906
#1  0x00007fff7c53bee5 in igtl::MessageBase::Unpack(int) (this=0x55555bf92350, crccheck=1)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink-build/OpenIGTLink/Source/igtlMessageBase.cxx:618
#2  0x00007fff7c20f7c6 in igtlioTrackingDataConverter::fromIGTL(igtl::SmartPointer<igtl::MessageBase>, igtlioBaseConverter::HeaderData*, igtlioTrackingDataConverter::ContentData*, bool, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<IANA_ENCODING_TYPE, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::pair<IANA_ENCODING_TYPE, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > >&)
    (source=..., header=0x55555bf8d540, dest=0x55555bf8d5c0, checkCRC=true, outMetaInfo=std::map with 0 elements)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink-build/OpenIGTLinkIO/Converter/igtlioTrackingDataConverter.cxx:33
#3  0x00007fff7c28bdea in igtlioTrackingDataDevice::ReceiveIGTLMessage(igtl::SmartPointer<igtl::MessageBase>, bool) (this=0x55555bf8d4f0, buffer=..., checkCRC=true)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink-build/OpenIGTLinkIO/Devices/igtlioTrackingDataDevice.cxx:73
#4  0x00007fff7c3185bc in igtlioConnector::ImportDataFromCircularBuffer() (this=0x55555ad5d990)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink-build/OpenIGTLinkIO/Logic/igtlioConnector.cxx:773
#5  0x00007fff7c318cb2 in igtlioConnector::PeriodicProcess() (this=0x55555ad5d990)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink-build/OpenIGTLinkIO/Logic/igtlioConnector.cxx:837
#6  0x00007fff7c3e9f63 in vtkMRMLIGTLConnectorNode::PeriodicProcess() (this=0x55555c1257c0)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink/OpenIGTLinkIF/MRML/vtkMRMLIGTLConnectorNode.cxx:2542
#7  0x00007fff7c60ca33 in vtkSlicerOpenIGTLinkIFLogic::CallConnectorTimerHander() (this=0x5555586867f0)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink/OpenIGTLinkIF/Logic/vtkSlicerOpenIGTLinkIFLogic.cxx:336
#8  0x00007fff7c683db4 in qSlicerOpenIGTLinkIFModule::importDataAndEvents() (this=0x55555820a2f0)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink/OpenIGTLinkIF/qSlicerOpenIGTLinkIFModule.cxx:219
#9  0x00007fff7c68598a in qSlicerOpenIGTLinkIFModule::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)
    (_o=0x55555820a2f0, _c=QMetaObject::InvokeMetaMethod, _id=3, _a=0x7fffffffd7d0)
    at /home/junichi/slicer/Modules-dev/SlicerOpenIGTLink-build/inner-build/OpenIGTLinkIF/moc_qSlicerOpenIGTLinkIFModule.cpp:90
#10 0x00007ffff58f17c8 in  () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#11 0x00007ffff58f57fe in QTimer::timeout(QTimer::QPrivateSignal) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#12 0x00007ffff58e733f in QObject::event(QEvent*) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#13 0x00007ffff656c713 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt5Widgets.so.5
#14 0x00007ffff78ec562 in qSlicerApplication::notify(QObject*, QEvent*) (this=0x7fffffffdd30, receiver=0x5555581daaa0, event=0x7fffffffda00)
    at /home/junichi/slicer/Slicer/Base/QTGUI/qSlicerApplication.cxx:518
#15 0x00007ffff58b9e3a in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#16 0x00007ffff59123eb in QTimerInfoList::activateTimers() () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#17 0x00007ffff5912cec in  () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#18 0x00007fffd2f1bd3b in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#19 0x00007fffd2f71258 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#20 0x00007fffd2f193e3 in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#21 0x00007ffff59130b8 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#22 0x00007ffff58b875b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#23 0x00007ffff58c0cf4 in QCoreApplication::exec() () at /lib/x86_64-linux-gnu/libQt5Core.so.5
#24 0x00007ffff6d121a6 in qSlicerCoreApplication::exec() () at /home/junichi/slicer/Slicer/Base/QTCore/qSlicerCoreApplication.cxx:1049
#25 0x000055555555d1f1 in (anonymous namespace)::SlicerAppMain(int, char**) (argc=1, argv=0x7fffffffdec8) at /home/junichi/slicer/Slicer/Applications/SlicerApp/Main.cxx:63
#26 0x000055555555d341 in main(int, char**) (argc=1, argv=0x7fffffffdec8) at /home/junichi/slicer/Slicer/Base/QTApp/qSlicerApplicationMainWrapper.cxx:56
(gdb) 
tokjun commented 12 months ago

The issue seems to be related to how igtlioConnector::ImportDataFromCircularBuffer() in the OpenIGTLinkIO library is implemented.

When an RTS_TDATA message is received, igtlioConnector::ImportDataFromCircularBuffer() creates an igtlioDevice instance based on the "base type name," which is TDATA, not RTS_TDATA. ImportDataFromCircularBuffer() then calls igtlioTrackingDataDevice::ReceiveIGTLMessage(), where the received message (RTS_TDATA) is copied into an igtl::TrackingDataMessage class instance (transMsg) (Line 29). This can destroy transMsg, and cause SIGSEGV in the subsequent lines.

tokjun commented 11 months ago

The issue has been resolved with the latest IGSIO/OpenIGTLinkIO.