2017-08-04 49 views
1

我正在写一个多线程程序,需要使用以下的bash行终止处理SIGQUIT SIGUSR1,并忽略其他SIGQUIT。 要忽略我写了这个信号:与调用sigwait

struct sigaction s; 
s.sa_handler=SIG_IGN; 
if((sigaction(SIGQUIT,&s,NULL))==-1) { 
    perror("sigaction"); 
    return -1; 
    } 

我写在指定的等待信号(handlerrno是检查errno和退出功能)线程以下代码:

sigset_t threadset; 
int err, sig; 
if(sigfillset(&threadset)==-1) handlerrno("Sigfillset thread stats"); 
if(sigdelset(&threadset,SIGQUIT)==-1) handlerrno("Sigdelset thread stats"); 
if(sigdelset(&threadset,SIGINT)==-1) handlerrno("Sigdelset thread stats"); 
if(sigdelset(&threadset,SIGTERM)==-1) handlerrno("Sigdelset thread stats"); 
if(sigdelset(&threadset,SIGUSR1)==-1) handlerrno("Sigdelset thread stats"); 
if((err=pthread_sigmask(SIG_SETMASK,&threadset,NULL))!=0)   
    handlerror(err,"Set sigmask thread stats"); 
if((err=sigwait(&threadset,&sig))!=0) handlerror(err,"Sigwait"); 
//I handle the signals here 

然而,当我从shell启动SIGQUIT时,指定等待信号的线程似乎卡在sigwait()中,所以我不知道会发生什么以及哪个线程获取信号。 代码有什么问题吗?谢谢!

回答

1

忽略掩码是全过程。在拨打sigaction后,SIQUIT永远不会在任何线程中挂起,因此sigwait将永远阻塞。

你应该做的是在创建任何线程之前阻塞主线程中的信号,以便子线程也阻止它(child threads inherit the signal mask of their parent thread)。

处理线程应该能够使信号出队,尽管它被阻塞了。

(我不知道你的终止信号的选择是否是一个很好的一个。SIQUIT通过Ctrl+\正常发送,预计将创建一个核心转储终止前,也许SIGTERM会是一个更好的选择。)

+0

谢谢!我需要终止这样的过程,因为这是大学的任务,所以我们的老师给了我们一个测试脚本,以确保代码的工作。 无论如何,问题在于处理线程是由主线程产生的,所以如果我在那里阻塞处理线程,它也会阻止它? – Gixuna

+0

正确。如果没有线程解除阻塞,并且在进程中只有一个sigwait调用处于活动状态,那么sigwait调用应该会得到它。 – PSkocik

+0

它的工作,非常感谢! – Gixuna