[Qt-interest] Delaying termination with QtService
BRM
bm_witness at yahoo.com
Tue Sep 21 22:45:28 CEST 2010
I'm using the QtService (2.6.1, I think - I've had it for quite a while now)
from the Qt Solutions for a series of programs under Qt 4.5.1. They mostly run
under Linux.
The program had been working just fine; however, a new feature requires that I
be able to do some things before shutdown - namely notifying another program -
which requires waiting for a response back.
Looking over the code, then it receives the stop/terminate command the QtService
under Unix (qtservice_unix.cpp) simply does:
if (!(serviceFlags & QtServiceBase::CannotBeStopped)) {
QtServiceBase::instance()->stop()
QCoreApplication->quit()
}
stop() ends up calling down into the class that is the program. I originally
tried to do the notice as part of the call to stop(); however, the program would
terminate without actually doing the notice, I'm guessing due to the direct call
by the qtservice class to QCoreApplication->quit() (qtservice_unix.cpp:329 or
thereabout). So I tried devising a new method...
To add the delaying, I added another flag to the QtService; if the flag is set,
then instead of calling QCoreApplication()->quit() it calls another function -
QtServiceBase::instance()->scheduleTerminate():
if (!(serviceFlags & QtServiceBase::CannotBeStopped)) {
QtServiceBase::instance()->stop();
if ((serviceFlags & QtServiceBase::DelayQuit)) {
QtServiceBase::instance()->scheduleTerminate();
} else {
QCoreApplication::instance()->quit();
}
retValue = true;
}
Like stop(), scheduleTerminate() calls down to the class that is the program so
the program can schedule a termination event.
My class, then issues a single shot timer (preferred since I don't need to
create a QTimer object for this) to itself to check a variable that denotes it
is ready to terminate (the variable is set as a result of response back),
essentially:
myService::checkTerminate() {
if (readyTerminate == false) {
QTimer::singleShot(10,this,SLOT(checkTerminate())); // check the flag
every 10 ms
} else {
QTimer::singleShot(0,QCoreApplication::instance(),SLOT(quit()));
}
}
For the most part this works - the program does see the shutdown, does the
notification, gets the response back; except, it then crashes in response to the
call to quit().
Tracing through it, the QThread exits the run() and begins clean up
(thread/qthread_unix.cpp:191), and goes to finish()
(thread/qthread_unix.cpp:199), which then goes through relocking a mutex. Only,
the QMutex::d's value is 0x11, so it crashes on the dereference of the mutex
when it's going through the relock (qmutex.h:102 -> qmutex.h:120 ->
qmutex.cpp:152).
Prior to this change, the program would terminate without any problems. The only
delta is the changes to support this, which seems to be just fine up until the
use of the QMutex.
Or is there some better way to accomplish what I want to do?
TIA,
Ben
More information about the Qt-interest-old
mailing list