PDA

View Full Version : Clean shutdown console application



redlars
10th September 2013, 11:27
Using QT 4.7 on Windows\Linux platform.

Used QProcess to create child process in primary application and this works. The child process is a console application that looks like this;



int main(int argc, char* args[])
{
QCoreApplication app(argc, args);

// create application objects

return app.exec();
}


What is the recommended approach to terminate the child application from the primary process that allows for clean-up being performed on Windows and Linux?

Ideally I would like an approach that is event driven in the child process, as opposed to polling a status at intervals or a blocking call.

The QProcess::terminate documentation states: "Console applications on Windows that do not run an event loop, or whose event loop does not handle WM_CLOSE message, can only be terminated by calling Kill."

How do we know if an event loop handles WM_CLOSE message? The QCoreApplication docs does not reference specific Windows messages like WM_CLOSE.

The QProcess::kill uses TerminateProcess (Windows) and SIGKILL signal (Linux) which wont allow application clean-up which is important in this case.

The SetConsoleCtrlHandler method only works on Windows which is not ideal. The method is triggered by Windows CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT events who are controlled by Windows OS. This does not cover the scenario that when the parent process is closed it should close the child process.

Appreciate any help.

redlars
11th September 2013, 12:12
Just an update.

Invoking QProcess::terminate() in the parent process does trigger an action in QEventDispatcherWin32:: processEvents with a message containing WM_CLOSE identifer. However the message is not added to the input queue for further processing. The below if statement is false (flags is equal 36 and QEventLoop::ExcludeUserInputEvents is equal 1).

Do not see any easy way to specify that the eventloop should handle WM_CLOSE. It is strange that the eventloop does not process this message.



if (haveMessage &&
(flags & QEventLoop::ExcludeUserInputEvents) ) &&
((msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) ||
(msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST) ||
msg.message == WM_MOUSEWHEEL ||
msg.message == WM_MOUSEHWHEEL ||
msg.message == WM_TOUCH)
msg.message == WM_CLOSE))
{
haveMessage= false;
d->queueUserInputEvents.append(msg);
}

anda_skoa
11th September 2013, 14:53
You parent process could create a sort of indicator file before launching the child.
The child then uses QFileSystemWatcher to be notified about its removal and then exit when that happens.

Another option is to use QLocalServer/QLocalSocket as an event driven communication channel between parent and child.

Cheers,
_