[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