Я заставил ребенка выполнить код очистки Qt с помощью обработчиков сигналов unix.
Вот объяснение высокого уровня:
- родитель открывает дочерний процесс, используя QProcess
- обработка происходит
- родитель закрывает дочерний процесс, используя QProcess :: terminate (), который вызывает сигнал SIGTERM для дочернего процесса
- ребенок реализует обработчик сигнала Unix для SIGTERM
- из обработчика сигнала unix qApp-> exit (0); происходит
- qApp испускает сигнал Qt "aboutToQuit ()"
- подключить слот дочернего процесса cleanup () к сигналу qApp aboutToQuit ()
Дочерний код процесса для обработки unix-сигнала SIGTERM:
static void unixSignalHandler(int signum) {
qDebug("DBG: main.cpp::unixSignalHandler(). signal = %s\n", strsignal(signum));
/*
* Make sure your Qt application gracefully quits.
* NOTE - purpose for calling qApp->exit(0):
* 1. Forces the Qt framework's "main event loop `qApp->exec()`" to quit looping.
* 2. Also emits the QCoreApplication::aboutToQuit() signal. This signal is used for cleanup code.
*/
qApp->exit(0);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MAINOBJECT mainobject;
/*
* Setup UNIX signal handlers for some of the common signals.
* NOTE common signals:
* SIGINT: The user started the process on the command line and user ctrl-C.
* SIGTERM: The user kills the process using the `kill` command.
* OR
* The process is started using QProcess and SIGTERM is
* issued when QProcess::close() is used to close the process.
*/
if (signal(SIGINT, unixSignalHandler) == SIG_ERR) {
qFatal("ERR - %s(%d): An error occurred while setting a signal handler.\n", __FILE__,__LINE__);
}
if (signal(SIGTERM, unixSignalHandler) == SIG_ERR) {
qFatal("ERR - %s(%d): An error occurred while setting a signal handler.\n", __FILE__,__LINE__);
}
// executes mainbobject.cleanupSlot() when the Qt framework emits aboutToQuit() signal.
QObject::connect(qApp, SIGNAL(aboutToQuit()),
&mainobject, SLOT(cleanupSlot()));
return a.exec();
}
Вывод:
I подтвердил, что это решение работает .
Я думаю, что это хорошее решение, потому что:
- позвольте родителю закрыть дочерний процесс таким образом, чтобы дочерний процесс выполнил очистку
- если родительский объект по ошибке закрывается и оставляет дочерний процесс запущенным, пользователь / sysadmin может уничтожить оставшийся дочерний процесс с помощью команды
kill
, и дочерний процесс все равно очистится после себя перед закрытием
p.s. «Почему бы просто не выполнить код очистки непосредственно в точке входа обработчика сигналов?»
Краткий ответ: вы не можете. Вот объяснение того, почему вы не можете выполнить свой код очистки Qt в функции обработчика сигналов unix. Из документации Qt "Вызов функций Qt из обработчиков сигналов Unix" :
Вы не можете вызывать функции Qt из обработчиков сигналов Unix. Стандарт
Применяется правило POSIX: Вы можете вызывать асинхронно-безопасные функции только из
обработчики сигналов. См. Сигнальные действия для полного списка функций.
Вы можете звонить из обработчиков сигналов Unix.