1

C ++で割り込み信号を処理してデストラクタを呼び出す方法に関連していますか? ですが、私の質問はプログラムの構造化に関するものです。

HDF5 ファイルにデータを書き出すシミュレーション プログラムを作成しています。ただし、プログラムが中断された場合は、蓄積されたデータを引き続き読み取れるように、HDF5 を適切に閉じてください。HDF5 ファイルへのハンドルを含む HDF5 ライター クラスを作成しました。そのクラスのデストラクタが呼び出されると、HDF5 ファイルが閉じられるはずです。したがって、Ctrl-C によるプログラムの中断が発生した場合は、SIGINT をキャッチしてデストラクタを呼び出したいと考えています。

私の読書によると、SIGINTまたはSIGSTPが発行された場合、デストラクタは呼び出されますか? のハンドラー関数はsigaction非常に単純で、フラグを変更するだけです。これにより、次のようなプログラムが作成されます (2 番目のリンクからコピー)...

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstring>
#include <atomic>

std::atomic<bool> quit(false);    // signal flag

void got_signal(int)
{
    quit.store(true);
}

class Foo
{
public:
    ~Foo() { std::cout << "destructor\n"; }
};

int main(void)
{
    struct sigaction sa;
    memset( &sa, 0, sizeof(sa) );
    sa.sa_handler = got_signal;
    sigfillset(&sa.sa_mask);
    sigaction(SIGINT,&sa,NULL);

    Foo foo;    // needs destruction before exit
    while (true)
    {
        // do real work here...
        sleep(1);
        if( quit.load() ) break;    // exit normally after SIGINT
    }
    return 0;
}

プログラム構造で、プログラムがフラグを頻繁にwhileチェックできるように、ループ内の部分を十分に短くする必要があることがわかります。quitしかし、私の問題は、私のプログラムが次のように構成されていることです。

int main()
{
     // set up variables

     HDF5Writer writer(...);

     run_simulation(&writer, [params]);
}

run_simulation指定された停止基準が満たされるまでシミュレーションを実行します。これには数分または数時間かかる場合があります。プログラムが何らかのフラグを監視するようにセットアップして、SIGINT を適切なタイミングで受信した後にシャットダウンするようにするにはどうすればよいですか?

4

1 に答える 1

0

おそらく、メイン ループの代わりに run_simulation() ルーチンにループを入れることができます。このルーチンのループは、前述の「グローバルな」揮発性原子変数を待ちます。これにより、ルーチンをシャットダウンする前にルーチンを終了できます

// included stuff

// flag
volatile sig_atomic_t no_signal = 1;

void sig_handler(int)
{
    --no_signal;
}

void run_simulation(...)
{
    // Maybe you put stuff on heap
    CMyClass* pMyObj = new CMyClass;

    do // at least once
    {
        // Maybe some stack stuff
        CMyClass oMyObj; // Dtor called when scope ends

        // Here you could already check if the signal has occurred,
        // to shut down in a timely manner
        if (no_signal)
            p_MyObj->do_stuff_that_takes_1_hour()
        else
            break;

    } while (no_signal)

    // clean up stuff
    delete p_MyObj;
    p_MyObj = nullptr; // if c++11
}

int Main()
{
    // Register sighandler

    // set up variables

    HDF5Writer writer(...);
    run_simulation(&writer, [params]);

    return 0;
}
于 2017-08-04T08:42:26.840 に答える