PDA

View Full Version : Issue emitting signal from background thread.



Chris@Link
2nd July 2012, 22:03
I have a class that I move to a background thread that constantly checks a server for updated settings. If the settings were updated then I emit a signal that forces the program to restart with the new settings. The problem I'm having is when I try to emit the signal it throws a segfault.

Where I connect this signal to the slot I want it to call.



connect(&settings_agent, SIGNAL(updatedSettingsNotification()), LCD,SLOT(restarting()));


This signal that I am trying to emit:



void SettingsFileRetrievalAgent::handleDeletedRegistrat ion()
{
emit updatedSettingsNotification(); //if delete registration, this can cause a crash (let it run maybe 15 seconds after startup).
}






This is the result from GDB Debugger:





Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 30704.0x7c2c]
0x6a2b0e31 in QObjectPrivate::isSignalConnected (this=0x0, signal_index=3)
at ../../include/QtCore/private/../../../../../../../ndk_buildrepos/qt-desktop/src/corelib/kernel/qobject_p.h:219
219 ../../include/QtCore/private/../../../../../../../ndk_buildrepos/qt-desktop/src/corelib/kernel/qobject_p.h: No
uch file or directory.
in ../../include/QtCore/private/../../../../../../../ndk_buildrepos/qt-desktop/src/corelib/kernel/qobject_p.h




The result when I do a bt:



#0 0x6a2b0e31 in QObjectPrivate::isSignalConnected (this=0x0, signal_index=3)
at ../../include/QtCore/private/../../../../../../../ndk_buildrepos/qt-desktop/src/cor
#1 0x6a2164d8 in QMetaObject::activate (sender=0x28d2cc, m=0x4a80cc, local_signal_index=1
at c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qobject.cpp:3201
#2 0x0041dced in ?? ()
#3 0x0040fd66 in ?? ()
#4 0x0041dc73 in ?? ()
#5 0x6a205ff8 in QMetaObject::metacall (object=0x28d2cc, cl=QMetaObject::InvokeMetaMethod
at c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qmetaobject.cpp:237
#6 0x6a210c9d in QMetaCallEvent::placeMetaCall (this=0xe0a67b8, object=0x28d2cc)
at c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qobject.cpp:535
#7 0x6a212ba8 in QObject::event (this=0x28d2cc, e=0xe0a67b8)
at c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qobject.cpp:1217
#8 0x0111bd88 in QApplicationPrivate::notify_helper (this=0xa0d6bb8, receiver=0x28d2cc, e
at c:\ndk_buildrepos\qt-desktop\src\gui\kernel\qapplication.cpp:4462
#9 0x011196da in QApplication::notify (this=0x28fe4c, receiver=0x28d2cc, e=0xe0a67b8)
at c:\ndk_buildrepos\qt-desktop\src\gui\kernel\qapplication.cpp:3862
#10 0x6a201540 in QCoreApplication::notifyInternal (this=0x28fe4c, receiver=0x28d2cc, even
at c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qcoreapplication.cpp:73 1
#11 0x6a268258 in QCoreApplication::sendEvent (receiver=0x28d2cc, event=0xe0a67b8)
at c:/ndk_buildrepos/qt-desktop/src/corelib/kernel//qcoreapplication.h:215
#12 0x6a2025eb in QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=0, d
at c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qcoreapplication.cpp:13 72
#13 0x6a2248e7 in qt_internal_proc (hwnd=0x440ba8, message=1025, wp=0, lp=0)
at c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qeventdispatcher_win.cp p:497
#14 0x75ed62fa in USER32!OffsetRect () from C:\Windows\syswow64\user32.dll
#15 0x00440ba8 in ?? ()
#16 0x75ed6d3a in USER32!IsWindow () from C:\Windows\syswow64\user32.dll
#17 0x6a22467e in qt_fast_timer_proc (timerId=0, user=4459432)
at c:\ndk_buildrepos\qt-desktop\src\corelib\kernel\qeventdispatcher_win.cp p:429
#18 0x75ed77c4 in USER32!AnyPopup () from C:\Windows\syswow64\user32.dll
#19 0x00000000 in ?? ()



this=0x0 I'm assuming this is the problem. I don't know if it's related to how the QThreads and Signals work, I just can't seem to figure out what the problem is. Any hints or ideas as to why this is happening would be great.

high_flyer
3rd July 2012, 10:56
show your code.
It seems 'LCD' is null.

Chris@Link
3rd July 2012, 16:01
Start a new thread and run the worker_thread()




QThread *settingsFileUpdaterThread = new QThread;
settings_agent.moveToThread(settingsFileUpdaterThr ead);
settingsFileUpdaterThread->start();
QMetaObject::invokeMethod(&settings_agent, "worker_thread", Qt::QueuedConnection);





void SettingsFileRetrievalAgent::worker_thread()
{
while(1)
status = updateSettingsIfPossible();

if (status == RETURN_SUCCESS_CACHE_UPDATED)
{
emit updatedSettingsNotification(); //segfault
}
for( int count = 0; count < 2; ++count )
sleep( 1 );
}
}


I have other threads that are just about identical and they don't seem to have a problem when emitting a signal.

high_flyer
3rd July 2012, 16:12
Right.
Where did you initialize 'LCD'?

Chris@Link
3rd July 2012, 16:17
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMetaObject::invokeMethod(this, "startup" , Qt::QueuedConnection);
}





void MainWindow::startup()
// Get pointer to layout manager for main window
QLayout* layout = this->layout();
// Add LCD screen to the main window layout at specified position
LCD = new(IPR5000_LCD)(this);
LCD->setGeometry(430,50,320,240);
LCD->setParent(this);
layout->addWidget(LCD);
}

high_flyer
3rd July 2012, 16:25
does this initialization happen before you start settingsFileUpdaterThread ?
If so, what exactly "restaring()" does?
Sound like a place where all kind of mischief can happen, if "restarting()" is re-spawning threads or similar thread related stuff - if this is the case - care has to be taken that things are all correctly terminated and initialized.
If you comment out all the content of "restarting()" does it still crash (the same way)?

Chris@Link
3rd July 2012, 16:37
void MainWindow::startup()
// Get pointer to layout manager for main window
QLayout* layout = this->layout();
// Add LCD screen to the main window layout at specified position
LCD = new(IPR5000_LCD)(this);
LCD->setGeometry(430,50,320,240);
LCD->setParent(this);
layout->addWidget(LCD);

KeyManagementAgent key_management_agent;
SettingsFileRetrievalAgent settings_agent( key_management_agent );
connect(&settings_agent, SIGNAL(updateSettingsNotification()), LCD, SLOT(restarting()));
// move it to its own thread and do stuff with it.
QThread *settingsFileUpdaterThread = new QThread;
settings_agent.moveToThread(settingsFileUpdaterThr ead);
settingsFileUpdaterThread->start();
QMetaObject::invokeMethod(&settings_agent, "worker_thread", Qt::QueuedConnection);

}



void IPR5000_LCD::restarting()
{
ui->stackedWidget->setCurrentIndex(2);
}



Like I said previously I do this sort of thing other places without problems so I don't see any reason there would be a problem with the 'LCD', it just happens to be this thread that is giving me issues.

Commenting out the code in the restarting() method still results in a segfault. I tried printing a simple debug message and it still crashes. I don't think it's a problem with the LCD class. The LCD slot is never called because the signal is never emitted, that's how I know it cant be the LCD.

Edit: It will loop about 5-8 times before it throws a segfault.

I really appreciate the help.

high_flyer
3rd July 2012, 16:58
1. Is 'key_management_agent' a parent for 'settings_agent' or just a parameter?
2. settings_agent is a stack variable, which dies at the end of the constructor. I would expect moveToThread() to have a problem with that - try allocating it on the heap.
This would also explain this==NULL.

Like I said previously I do this sort of thing other places without problems so I don't see any reason there would be a problem with the 'LCD', it just happens to be this thread that is giving me issues.
1.LCD was a likely candidate - since I don't know your code I wanted to rule it out.
2.I fail to see the relevance of the claim that something worked somewhere else since obviously its not *exactly* the same, and secondly, obviously it doesn't work here - so it helps little that it does somewhere else.
Specially when threads are in question - since alone different hardware (same software) may produce different results, or bring bugs to the surface on one system that are not see on another.
For your own good - stop thinking "this has to work" if it doesn't - rather "I must be doing something wrong if it doesn't work".
By the way, the code as you posted it, really requires no threads.

Chris@Link
3rd July 2012, 17:56
1. Is 'key_management_agent' a parent for 'settings_agent' or just a parameter?
2. settings_agent is a stack variable, which dies at the end of the constructor. I would expect moveToThread() to have a problem with that - try allocating it on the heap.
This would also explain this==NULL.


Upon further investigation the settings_agent and the key_management_agent was being destroyed after we finished the startup function. I don't know how I managed to overlook that but I did.



2.I fail to see the relevance of the claim that something worked somewhere else since obviously its not *exactly* the same, and secondly, obviously it doesn't work here - so it helps little that it does somewhere else.
Specially when threads are in question - since alone different hardware (same software) may produce different results, or bring bugs to the surface on one system that are not see on another.
For your own good - stop thinking "this has to work" if it doesn't - rather "I must be doing something wrong if it doesn't work".
By the way, the code as you posted it, really requires no threads.


I understand, I was extremely frustrated and I overlooked the fact that the stack variable was being destroyed.


Thanks for the help.