SIGSEGV
マルチスレッド環境でシグナルをキャッチすることが可能かどうか、または推奨される方法を知りたいです。SIGSEGV
のようなものによって発生したを処理することに特に興味があり*((int *)0) = 0
ます。
このトピックを読んだ結果、シグナル ハンドラをインストールするsignal()
とにたどり着きました。sigaction()
どちらもマルチスレッド環境では有望とは思えませんが。次に、他のスレッドのシグナルをブロックsigwaitinfo()
する前のpthread_sigmask()
呼び出しで、1 つのスレッドでシグナルを受信してみました。SIGSEGV
スレッド内で raise() を使用してシグナルが発生した範囲、またはkill -SIGSEGV
;のようなものによってプロセスに送信されたときに機能しました。ただし、\*((int*)0) = 0
それでもプロセスを強制終了します。私のテストプログラムは次のとおりです
void block_signal()
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGSEGV);
sigprocmask(SIG_BLOCK, &set, NULL);
if (pthread_sigmask(SIG_BLOCK, &set, NULL)) {
fprintf(stderr, "pthread_sigmask failed\n");
exit(EXIT_FAILURE);
}
}
void *buggy_thread(void *param)
{
char *ptr = NULL;
block_signal();
printf("Thread %lu created\n", pthread_self());
// Sleep for some random time
{ ... }
printf("About to raise from %lu\n", pthread_self());
// Raise a SIGSEGV
*ptr = 0;
pthread_exit(NULL);
}
void *dispatcher(void *param)
{
sigset_t set;
siginfo_t info;
int sig;
sigemptyset(&set);
sigaddset(&set, SIGSEGV);
for (;;) {
sig = sigwaitinfo(&set, &info);
if (sig == -1)
fprintf(stderr, "sigwaitinfo failed\n");
else
printf("Received signal SIGSEGV from %u\n", info.si_pid);
}
}
int main()
{
int i;
pthread_t tid;
pthread_t disp_tid;
block_signal();
if (pthread_create(&disp_tid, NULL, dispatcher, NULL)) {
fprintf(stderr, "Cannot create dispatcher\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; ++i) {
if (pthread_create(&tid, NULL, buggy_thread, NULL) {
fprintf(stderr, "Cannot create thread\n");
exit(EXIT_FAILURE);
}
}
pause();
}
予期せず、プログラムはレイザーのスレッド ID を出力する代わりにセグメンテーション違反で終了します。