[英]Signal handling in pthreads
我創建了一個pthread,並在其中安裝了一個信號處理程序,與main( )
函數中的方式相同。 線程的信號處理程序是一個單獨的函數。 令人驚訝的是,它不起作用,即線程的信號處理程序無法捕獲信號。
這是代碼:
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
typedef struct data
{
char name[10];
int age;
}data;
void sig_func(int sig)
{
printf("Caught signal: %d\n",sig);
signal(SIGSEGV,sig_func);
}
void func(data *p)
{
printf("This is from thread function\n");
signal(SIGSEGV,sig_func); // Register signal handler inside thread
strcpy(p->name,"Mr. Linux");
p->age=30;
sleep(2); // Sleep to catch the signal
}
int main()
{
pthread_t tid;
pthread_attr_t attr;
data *ptr;
pthread_attr_init(&attr);
pthread_create(&tid,&attr,(void*)func,ptr);
pthread_kill(tid,SIGSEGV);
pthread_join(tid,NULL);
printf("Name:%s\n",ptr->name);
printf("Age:%d\n",ptr->age);
}
輸出:
分段錯誤(這意味着信號不會被處理程序捕獲)
您的代碼有幾個問題:
ptr
未初始化,因此所有ptr->
部件都會使程序崩潰 pthread_kill()
,並且在一個線程中(具有未指定的行為) printf()
,這不保證工作(參見man 7 signal
for a safe functions) 雖然你仍然需要正確的線程同步,並且如其他地方所述,你應該使用sigaction()
:
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
typedef struct data
{
char name[10];
int age;
}data;
void sig_func(int sig)
{
write(1, "Caught signal 11\n", 17);
signal(SIGSEGV,sig_func);
}
void func(data *p)
{
fprintf(stderr, "This is from thread function\n");
strcpy(p->name,"Mr. Linux");
p->age=30;
sleep(2); // Sleep to catch the signal
}
int main()
{
pthread_t tid;
pthread_attr_t attr;
data d;
data *ptr = &d;
signal(SIGSEGV,sig_func); // Register signal handler before going multithread
pthread_attr_init(&attr);
pthread_create(&tid,&attr,(void*)func,ptr);
sleep(1); // Leave time for initialisation
pthread_kill(tid,SIGSEGV);
pthread_join(tid,NULL);
fprintf(stderr, "Name:%s\n",ptr->name);
fprintf(stderr, "Age:%d\n",ptr->age);
}
編輯 :在主線程中安裝sighandler
我認為問題的核心是信號作為一個整體傳遞給整個過程,而不是單個線程。 通常,提名單個線程來處理所有信號; 所有其他線程(包括主線程)需要使用pthread_sigmask()
來阻塞信號 。
您可以設置掩碼以阻止所有信號,啟動信號處理程序線程,取消屏蔽您希望處理的信號,然后返回主線程,啟動您需要的所有其他線程。 他們將從主線程繼承“阻止所有信號”掩碼。
順便提一下,是時候離開signal(3)
並切換到sigaction(2)
,它具有可靠的語義並且更好地標准化。 (因此更便攜。)
你沒有提到的代碼的一個問題是,雖然信號阻塞(和交付,如果你使用pthread_kill
或raise
)是每個線程,信號處理程序是每個進程。 這意味着它們是一種非常糟糕的線程間通信機制,特別是如果您的代碼將被用作庫代碼,因為對於庫來說,改變調用者的信號處理程序是非常糟糕的行為。
還要注意,與線程信號的其他方法(如條件變量或障礙)相比,使用信號處理程序進行線程之間的通信具有次優性能,因為至少有一個額外的用戶 - 內核 - 用戶轉換(當信號處理程序返回時)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.