我用下面的例子工作(這是基於聯機幫助頁在linux pthread_sigmask的例子):信號用C處理與流程和2個線程不工作
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
/* Simple error handling functions */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void * silly_worker(void *arg)
{
for(int index=0,max=5; index<max; ++index) {
printf("waiting %d of %d\n",index,max);
sleep(1);
}
puts("Finished waiting. Here comes the SIGSEGV");
strcpy(NULL,"this will crash");
}
static void *
sig_thread(void *arg)
{
sigset_t *set = (sigset_t *) arg;
int s, sig;
for (;;) {
s = sigwait(set, &sig);
if (s != 0)
handle_error_en(s, "sigwait");
printf("Signal handling thread got signal %d\n", sig);
}
}
int
main(int argc, char *argv[])
{
pthread_t thread;
pthread_t thread2;
sigset_t set;
int s;
/* Block SIGINT; other threads created by main() will inherit
a copy of the signal mask. */
sigemptyset(&set);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGSEGV);
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
handle_error_en(s, "pthread_sigmask");
s = pthread_create(&thread, NULL, &sig_thread, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");
/* Main thread carries on to create other threads and/or do
other work */
s = pthread_create(&thread2, NULL, &silly_worker, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");
pause(); /* Dummy pause so we can test program */
}
據該男子頁面,這應該捕獲由silly_worker線程生成的SIGSEGV。但事實並非如此。事實上,我不確定哪個機構能夠獲得信號。當程序運行時,我得到下面的輸出:
waiting 0 of 5
waiting 1 of 5
waiting 2 of 5
waiting 3 of 5
waiting 4 of 5
Finished waiting. Here comes the SIGSEGV
Segmentation fault
你可以看到,信號處理程序不輸出「段錯誤」的字符串,因此它必須從默認的處理器到來。如果是默認值,那麼它會破壞該示例的目的 - 設置信號處理程序並捕獲信號並對它們執行某些操作。
我可以找到很多處理程序的例子,但沒有一個適用於這種情況:它們都沒有演示一個導致真正明顯的SIGSEGV的線程,並捕獲並報告自定義處理程序中的錯誤。
問題依然存在:如何獲取自定義信號處理程序以從此SIGSEGV'ing線程獲取信號?
這是否適用於SIGINT等其他信號?一些像SIGSEGV和SIGILL這樣的信號是同步的,並且總是被傳遞給引起它們的線程。我不確定sigwait是否可以處理這些問題。 –
請注意,「Segmentation fault」(分段錯誤)通常由Shell在看到您的進程被SIGSEGV信號終止時打印出來。 – Neil
它適用於其他信號,但這不會有幫助:我試圖捕獲SIGSEGV具體。在main()和沒有線程的單個循環中,我可以捕獲SIGSEGV,這完全沒有問題。當線程發揮作用時,它似乎並不正確。 –