2

中間体 signal_handlers を使用せずにクラッシュするスレッドの ID をキャッチする簡単な方法があるかどうか知りたい

次のコードがあります

void signal_handler(int signal)
{
  std::cout << "Caught the signal:" << signal << std::endl;
}

void    handler_t1(int signal)
{
  std::signal(SIGSEGV, signal_handler);
  std::cout << "Thread 1 have received the signal: " << signal << std::endl;
  std::raise(SIGSEGV);
}

void    f1()
{
  std::signal(SIGSEGV, handler_t1);
  std::cout << "Begin thread 1" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(1));
  std::raise(SIGSEGV);
  std::cout << "end thread1" << std::endl;
}

void    f2()
{
  std::cout << "Begin thread 2" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(3));
  std::cout << "end thread2" << std::endl;
}

int     main()
{
  std::thread t1(f1);
  std::thread t2(f2);

  t1.join();
  t2.join();
}

だから私は得る

Begin thread 1Begin thread 2
Thread 1 have received the signal: 11
Caught the signal:11
end thread1
end thread2

しかし、5 つのスレッドがある場合、5 つの handler を作成することを避けることができますか?

編集私のインクルードは

#include <thread>
#include <chrono>
#include <iostream>
#include <csignal>

編集https://stackoverflow.com/a/16259324/2380470 を見つけたようなものを探していたと思い が、このことはまだ存在しないので、何か他のものを見つける必要があります

4

2 に答える 2

4

あなたの質問に対する答えは「いいえ」です。ソフトウェア割り込みが非同期で実行されるスレッドを制御できます (特定のスレッドでシグナルをブロックすることにより)。また、POSIX プラットフォームでは、すべてのスレッドでシグナルの非同期実行をブロックし、代わりに sigwait() を使用して専用スレッドでシグナルに応答できます。しかし、割り込みが kill() の呼び出しによって発生する場合、または SIGSEGV などのシステム生成割り込みである場合、POSIX には、どのスレッドがシグナルを生成したかをシグナルハンドラーで判断する標準的な方法がありません。

スレッドはシグナルを「スロー」しないことに注意してください。また、これは C++ 標準に関連していないことにも注意してください。

編集あなたのコメンターの 1 人が、シグナルが生成されたスレッドでシグナル ハンドラーが実行されると想定している可能性があることに気付きました。raise() の呼び出しの場合を除いて、そうではありません。kill() から発生したシグナル、またはシステムが生成したシグナルは、そのシグナルをブロックしていないスレッドで非同期に実行できます。複数のスレッドでシグナルがブロックされていない場合、どのスレッドが中断されるかは未定義です (システムとそのスケジューラの選択です)。また、割り込みがユーザーによって生成される場合、POSIX では、kill() の代わりに sigqueue() を呼び出すことができ、sigqueue は、呼び出し元の ID などを識別できるユーザー データ値を渡すことができることにも注意してください。ただし、それは明らかに SIGSEGV とは無関係です。POSIXでは、pthread_kill() を使用すると、呼び出しが行われたプロセス内の特定のスレッドに信号を割り込ませることもできます (ただし、これは呼び出し元を識別せず、SIGSEGV にも関係しません)。マルチスレッド プログラムでの raise() は、 pthread_kill() への呼び出しとして効果があります (これは raise() を呼び出すスレッドで実行されます: ただし、raise() は情報を渡す目的には役に立ちません)。

于 2013-07-24T18:09:34.590 に答える