QProcess :: close () вызывает Unix сигнал SIGTERM в процессе? - PullRequest
1 голос
/ 21 сентября 2011

В Linux / Qt у меня есть приложение с графическим интерфейсом. GUI запускает дополнительные дочерние процессы, используя QProcess. Чтобы закрыть дочерние процессы, я использую QProcess :: close ().

Создает ли QProcess :: close () сигнал SIGTERM unix для дочернего процесса?

(Я связался с документацией Qt для QProcess и close (), потому что из документации не могу сказать, был ли поднят сигнал unix ...)

ОБНОВЛЕНИЕ: изменен вопрос о конкретном сигнале Unix: SIGTERM.

Ответы [ 2 ]

3 голосов
/ 22 сентября 2011

Сегодня я узнал, что QProcess :: close () не вызывает сигнал SIGTERM.Чтобы устранить эту проблему, я фиксирую stderr и stdout дочернего процесса. Спойлер: QProcess :: terminate () вызывает сигнал SIGTERM.


Дочерний код процесса для обработки 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();
}

Код родительского процессакоторый обрабатывает close () или terminate () дочернего элемента:

if(this->childProcess1!=NULL && this->childProcess1->state()==QProcess::Running) {
    this->childProcess1->terminate(); // raise unix SIGTERM signal on the process (let's it execute cleanup code)
    if(childProcess1->waitForFinished() == false) {
        qDebug("DBG - MainWindow::close(): Failed to close childProcess1.");
        qDebug() << "DBG - childProcess1->exitCode     =" << childProcess1->exitCode();
        qDebug() << "DBG - childProcess1->ExitStatus   =" << childProcess1->exitStatus();
        qDebug() << "DBG - childProcess1->error()      =" << childProcess1->error();
        qDebug() << "DBG - childProcess1->errorString()=" << childProcess1->errorString();
    }
}
if(this->childProcess2!=NULL && this->childProcess2->state()== QProcess::Running) {
    this->childProcess2->terminate(); // raise unix SIGTERM signal on the process (let's it execute cleanup code)
    if(childProcess2->waitForFinished() == false) {
        qDebug("DBG - MainWindow::close(): Failed to close childProcess2.");
        qDebug() << "DBG - childProcess2->exitCode     =" << childProcess2->exitCode();
        qDebug() << "DBG - childProcess2->ExitStatus   =" << childProcess2->exitStatus();
        qDebug() << "DBG - childProcess2->error()      =" << childProcess2->error();
        qDebug() << "DBG - childProcess2->errorString()=" << childProcess2->errorString();
    }
}

Когда родитель использует QProcess::terminate(), вывод дочернего процесса:

"DBG: main.cpp::unixSignalHandler(). signal = Terminated

Когда родитель использует `QProcess :: close (), выход дочернего процесса:

DBG - PARENTOBJECT::close(): Failed to close childProcess.
DBG - childProcess->exitCode     = 0 
DBG - childProcess->ExitStatus   = 1 
DBG - childProcess->error()      = 1 
DBG - childProcess->errorString()= "Unknown error" 

Выход из эксперимента terminate() доказывает, что дочерний процесс получает сигнал SIGTERM.

Выход изclose() эксперимент доказывает, что дочерний процесс не получает сигнал SIGTERM.


Вывод:

Если вы хотите отправить дочернему процессу сигнал SIGTERM, используйтеQProcess :: прекратить ().

2 голосов
/ 21 сентября 2011

Да, я смотрю на исходный код qprocess.cpp и проходит через некоторые движения, чтобы приятно свернуть процесс, затем вызывает общий обработчик, а затем передает terminateProcess в qprocess_unix, который SIGTERM выполняет в процессе.

...