Strange crash related to TMonitor and GUI (Signals?)

Hi

I’m working on a complex DAQ application including a GUI and I’m having a strange issue, probably related to TMonitor, the GUI, and signals.

I’m using a TServerSocket including a TMonitor (as shown in the corresponding tutorials) for data forwarding. The code seems to work when I’m not using the GUI.

When using the GUI, my application crashes as soon as I move the mouse inside a TCanvas or a TGListTree (both of which have their ProcessedEvent() signals connected to custom handler methods).

Debugging with gdb gives me the output below. I see there is some mismatch in the arguments of the ProcessedEvent() signal but I don’t understand how this should be related to the open socket.

ROOT::EnableThreadSafety() is active but didn’t have any effect.

Many thanks,
Dominik

spectr-gui: /tmp/root-6.36.02/interpreter/llvm-project/clang/include/clang/AST/Decl.h:2669: const clang::ParmVarDecl* clang::FunctionDecl::getParamDecl(unsigned int) const: Assertion `i < getNumParams() && "Illegal param #"' failed.

Thread 1 "spectr-gui" received signal SIGABRT, Aborted.
0x00007ffff388bedc in __pthread_kill_implementation () from /usr/lib64/libc.so.6
#1  0x00007ffff383eb46 in raise () from /usr/lib64/libc.so.6
#2  0x00007ffff3828833 in abort () from /usr/lib64/libc.so.6
#3  0x00007ffff382875b in __assert_fail_base.cold () from /usr/lib64/libc.so.6
u#4  0x00007ffff3837886 in __assert_fail () from /usr/lib64/libc.so.6
#5  0x00007fffe686f7f6 in clang::FunctionDecl::getParamDecl (this=0x58c6c50, i=1)
    at /tmp/root-6.36.02/interpreter/llvm-project/clang/include/clang/AST/Decl.h:2669
2669	    assert(i < getNumParams() && "Illegal param #");
#6  0x00007fffe68ccc3b in TClingCallFunc::exec (this=0x693d5c0, address=0x275b390, ret=0x0)
    at /tmp/root-6.36.02/core/metacling/src/TClingCallFunc.cxx:1450
1450	           QT = FD->getParamDecl(i)->getType();
#7  0x00007fffe68cdf22 in TClingCallFunc::Exec (this=0x693d5c0, address=0x275b390, interpVal=0x0)
    at /tmp/root-6.36.02/core/metacling/src/TClingCallFunc.cxx:1537
1537	      exec(address, nullptr);
#8  0x00007fffe6727c22 in TCling::CallFunc_Exec (this=0x59c4d0, func=0x693d5c0, address=0x275b390)
    at /tmp/root-6.36.02/core/metacling/src/TCling.cxx:7910
up7910	   f->Exec(address);
#9  0x00007ffff7172496 in TQConnection::SendSignal (this=0x693d3e0) at /tmp/root-6.36.02/core/base/inc/TQConnection.h:76
76	      gInterpreter->CallFunc_Exec(func, address);
#10 0x00007ffff7d5ede7 in TQObject::EmitVA<long> (this=0x1325230, signal_name=0x7ffff7e69655 "ProcessedEvent(Event_t*)")
    at /modsi/dist/root/rhel9/6.36.02-debug/include/TQObject.h:137
137	         connection->SendSignal();
#11 0x00007ffff7d5eb18 in TQObject::Emit<long> (this=0x1325230, signal=0x7ffff7e69655 "ProcessedEvent(Event_t*)", arg=@0x7fffffffbc98: 140737488338336)
    at /modsi/dist/root/rhel9/6.36.02-debug/include/TQObject.h:167
167	      EmitVA(signal, placeholder, arg);
#12 0x00007ffff7d5e0dd in TGFrame::ProcessedEvent (this=0x13251e0, event=0x7fffffffbda0) at /modsi/dist/root/rhel9/6.36.02-debug/include/TGFrame.h:182
182	                     { Emit("ProcessedEvent(Event_t*)", (Longptr_t)event); } //*SIGNAL*
#13 0x00007ffff436dbb4 in TGFrame::HandleEvent (this=0x13251e0, event=0x7fffffffbda0) at /tmp/root-6.36.02/gui/gui/src/TGFrame.cxx:576
576	      ProcessedEvent(event);  // emit signal
#14 0x00007ffff4322252 in TGClient::HandleEvent (this=0x26a1990, event=0x7fffffffbda0) at /tmp/root-6.36.02/gui/gui/src/TGClient.cxx:853
853	   w->HandleEvent(event);
#15 0x00007ffff4321b57 in TGClient::ProcessOneEvent (this=0x26a1990) at /tmp/root-6.36.02/gui/gui/src/TGClient.cxx:663
663	         HandleEvent(&event);
#16 0x00007ffff4321cf0 in TGClient::HandleInput (this=0x26a1990) at /tmp/root-6.36.02/gui/gui/src/TGClient.cxx:710
710	   while (ProcessOneEvent())
#17 0x00007ffff43202c4 in TGInputHandler::Notify (this=0x2461650) at /tmp/root-6.36.02/gui/gui/src/TGClient.cxx:117
117	   return fClient->HandleInput();
#18 0x00007ffff72b8321 in TUnixSystem::DispatchOneEvent (this=0x492c20, pendingOnly=false) at /tmp/root-6.36.02/core/unix/src/TUnixSystem.cxx:1099
1099	      if (gXDisplay && gXDisplay->Notify()) {
#19 0x00007ffff71a1b33 in TSystem::InnerLoop (this=0x492c20) at /tmp/root-6.36.02/core/base/src/TSystem.cxx:403
403	   DispatchOneEvent();
#20 0x00007ffff71a18c8 in TSystem::Run (this=0x492c20) at /tmp/root-6.36.02/core/base/src/TSystem.cxx:353
353	            InnerLoop();
#21 0x00007ffff71152b9 in TApplication::Run (this=0x7fffffffc020, retrn=false) at /tmp/root-6.36.02/core/base/src/TApplication.cxx:1896
1896	   gSystem->Run();
#22 0x000000000041b0c1 in main (argc=2, argv=0x7fffffffd018) at MainSpectR.cxx:93
93	    app.Run();

ROOT Version: 6.36.02
Platform: linuxx8664gcc
Compiler: c++ (GCC) 11.5.0 20240719 (Red Hat 11.5.0-5)


Can you provide a minimal reproducer we can actually run? I’m afraid there is not much we can do with only the stack trace…

The application is 33k SLOC so extracting a reproducer is not straightforward. I’ll see what I can do. I was hoping an expert of Clang, signal/slot, or the GUI could give me some suggestions from the stack trace.

Well, I know the GUI and the signal/slot, but it is difficult to guess from the stack trace. My advice would be to try to catch it in the debugger…

The stack trace has been captured with the debugger and a debug version of ROOT so the lines in the ROOT classes are visible. As I interpret it, there is some problem with the number of arguments passed in TGFrame::ProcessEvents(Event_t*) where in principle TCanvas::ProcessEvent(Int_t, Int_t, Int_t, TObject*) should be called when I move the mouse into the TCanvas. But I don’t get why some “wrong” connections on the GUI side should be affected by opening sockets in a DAQ driver…

Hard to tell. As I said, it looks like there is a bug somewhere, and guessing where is difficult without a single line of code. Since it is in the GUI, and I know debugging a GUI session is hard, I sometimes use the good old “printf” way… And signal/slot can be evil sometimes