簡體   English   中英

pthreads中的信號處理

[英]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_killraise )是每個線程,信號處理程序是每個進程。 這意味着它們是一種非常糟糕的線程間通信機制,特別是如果您的代碼將被用作庫代碼,因為對於庫來說,改變調用者的信號處理程序是非常糟糕的行為。

還要注意,與線程信號的其他方法(如條件變量或障礙)相比,使用信號處理程序進行線程之間的通信具有次優性能,因為至少有一個額外的用戶 - 內核 - 用戶轉換(當信號處理程序返回時)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM