8

SIGINTシグナルを受信したときにマルチスレッドC++11アプリケーションを正しく終了しようとしていますが(^Cそうです)、メインスレッドはそれに応答しますが、何らかの理由で子スレッドに伝播しません。

たとえば、(以下のコードサンプルのように)スレッド内にブロッキング関数がある場合、たとえば関数を使用してSIGNTフックをインストールすると、sleep()すべての制御が失われます。^Csigaction()

そのような動作を修正または回避する方法はありますか?主に受信した信号を子スレッドに伝播する方法はありますか?

編集:POSIXsleep()をC++11に置き換えましたstd::this_thread::sleep_for()

#include <iostream>
#include <thread>
#include <chrono>
#include <signal.h> // for sigaction() function 

static int signaled = 0;

void threaded_foo() {
  while (!signaled) {
    // pressing ^C now will not lead to correct termination, because we are
    // sleeping for a long time (100500 seconds) and do not respond to
    // SIGINT for some tricky reason i am looking a bypassage for.
    std::chrono::seconds duration(100500);
    std::this_thread::sleep_for(duration);
  }
  std::cout << "Correct termination\n";
}

void sighandler(int sig, siginfo_t *siginfo, void *context) {
  signaled = 1;
}

void install_sig_hooks() {
  struct sigaction action;
  memset(&action, 0, sizeof(struct sigaction));
  action.sa_sigaction = sighandler;
  action.sa_flags     = SA_SIGINFO;
  sigaction(SIGINT, &action, NULL);
}

int main(int argc, char **argv) {
  install_sig_hooks();

  std::thread t(threaded_foo);
  t.join();
  return 0;
}

EDIT2 したがって、解決策は、すべてのブロッキング呼び出しを非ブロッキングの対応物と、条件変数やポーリングなどのメカニズムに置き換えることでした。

現在のソフトウェア(および場合によってはハードウェア)は、信号を受信したときに他の人に何をすべきかを指示することになっている1つのスレッドで信号を処理するように設計されていないため、実際の質問には答えられません。

4

1 に答える 1

4

SIGINTシグナル(^ C)を受信すると、マルチスレッドC ++ 11アプリケーションを正しく終了しようとしていますが、メインスレッドは適切に応答しますが、何らかの理由で子スレッドに伝播しません。

POSIXは、プロセスまたはスレッドを対象とするシグナルを区別します。いずれの場合も、1つのスレッドのみがシグナルを受信します。

生成時に、信号がプロセスに対して生成されたか、プロセス内の特定のスレッドに対して生成されたかを判断する必要があります。ハードウェア障害など、特定のスレッドに起因する何らかのアクションによって生成される信号は、信号の生成を引き起こしたスレッドに対して生成されるものとします。プロセスIDまたはプロセスグループID、あるいは端末アクティビティなどの非同期イベントに関連して生成される信号は、プロセスに対して生成されるものとします。

..。

...プロセス用に生成された信号は、その信号を選択するsigwait()関数の呼び出し中、または信号の配信をブロックしていないプロセス内のスレッドの1つに配信される必要があります。そのシグナルを選択するsigwait()関数の呼び出しにスレッドがなく、プロセス内のすべてのスレッドがシグナルの配信をブロックする場合、スレッドがそれを選択するsigwait()関数を呼び出すまで、シグナルはプロセスで保留されたままになります。シグナル、スレッドがシグナルの配信のブロックを解除するか、シグナルに関連付けられたアクションがシグナルを無視するように設定されます。

マルチスレッドプロセスでは、一般的な解決策は、1つを除くすべてのスレッドで処理する予定のプロセス信号をブロックすることです。その1つのスレッドは通常、すべてのプロセスシグナルを処理し、他のスレッドに何をすべきか(たとえば終了)を指示します。

また、signaledはシグナルハンドラーによって設定されるため、宣言する必要がありますvolatile。これは、次の2つのユースケースのうちの1つvolatileです。

static int volatile signaled = 0;
于 2013-03-27T12:06:22.973 に答える