linux - Qt子プロセスを閉じて、子プロセスにクリーンアップコードを実行させるにはどうすればよいですか?

linux qt process ipc child-process

Linux / Qtでプロセスを開始してから、QProcessを使用していくつかの子プロセスを開始します。次に、最終的には子プロセスを適切に閉じます(クリーンアップコードを実行します)。

子プロセスはQSharedMemoryを使用していて、現在QProcess::close()を呼び出すと、QSharedMemory::detach()を呼び出さずに子プロセスが閉じられ、その結果、すべてのプロセスが閉じられますが、残っています。クリーンアップされていない共有メモリ上。

子プロセスのコードがあり、コードには関数cleanup()があります。親プロセスは、子プロセスがcleanup()を実行できるようにQProcessをどのように閉じますか?
答え
子供にUnixシグナルハンドラーを使用してQtクリーンアップコードを実行させました。

これは高レベルの説明です:


親はQProcessを使用して子プロセスを開きます
処理が発生します
親はQProcess::terminate()を使用して子プロセスを閉じ、子プロセスでSIGTERMシグナルを発生させます


(QProcess::close() because it doesn't raise the SIGTERM signalは使用しないでください)

子がSIGTERMのUNIXシグナルハンドラを実装する
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();
}




結論:

confirmed that this solution works

私はこれが良い解決策だと思います:


親が子プロセスをクリーンアップを実行するような方法で子プロセスを閉じましょう
親が誤って閉じて子プロセスを実行したままにした場合、ユーザー/システム管理者はkillコマンドを使用して残りの子プロセスを強制終了でき、子プロセスは閉じる前にそれ自体をクリーンアップします




PS 「クリーンアップコードをシグナルハンドラのエントリポイントで直接実行しないのはなぜですか?」

簡単な答えは、あなたができないからです。 unixシグナルハンドラー関数でQtクリーンアップコードを実行できない理由を説明します。 Qt documentation "Calling Qt Functions From Unix Signal Handlers"から:


UnixシグナルハンドラーからQt関数を呼び出すことはできません。標準
POSIXルールが適用されます。非同期シグナルセーフ関数は、
シグナルハンドラ。関数の完全なリストについては、Signal Actionsを参照してください
Unixシグナルハンドラから呼び出すことができます。
関連記事

linux - マシンチェック例外をシミュレートまたはトリガーする方法

linux - この「共有メモリ」のIPCオブジェクトは削除されていますか? [重複]

c - Linuxキャリア検出通知

linux - LinuxでのTomcat Webアプリケーション構成

linux - gitはすべて最新のものを言います

android - ソースコード/ドライバーAndroid携帯電話の開放性

c - pthread_mutex_timedlockとデッドロック

linux - Linuxで同等のdebugview

c - リアルタイム信号の意義は?

php - PHPでWHMのプラグインを作成することは可能ですか?