2016-07-21 42 views
2

我有一个基本的问题,处理信号多线程过程。mutlti-threaded过程中的信号处理

在我的代码,我创建从主线程一个子线程,听一个SIGALRM这将是由主线程后触发(使用其他功能一样timer_create给了我同样的结果,所以请不要关注在此)。

问题是,而不是捕捉信号,整个过程终止与控制台上一个奇怪的“闹钟”输出。

这是我的代码:

#include <iostream> 
#include <sys/time.h> 
#include <unistd.h> 
#include <csignal> 

using namespace std; 

void* run_something(void* args){ 
    //unblock the SIGALRM to be catched 
    sigset_t sig; 
    sigemptyset(&sig); 
    sigaddset(&sig, SIGALRM); 
    sigprocmask(SIG_UNBLOCK, &sig, NULL); //tried with pthread_sigmask 

    //wait for SIGALRM 
    int catchedSig; 
    sigwait(&sig, &catchedSig); 
    cout<<"in sub-thread, SIGALRM catched, return"<<endl; 
} 

int main(int argc, char** argv){ 
    //block SIGALRM in main thread 
    sigset_t sig; 
    sigemptyset(&sig); 
    sigaddset(&sig, SIGALRM); 
    sigprocmask(SIG_BLOCK, &sig, NULL); 

    //create new thread 
    pthread_t thread; 
    pthread_attr_t attr; 
    pthread_attr_init(&attr); 
    pthread_create(&thread, &attr, run_something, NULL); 

    //trigger SIGARLM after 2s 
    alarm(2); //tried with timer_create/sigevent 

    //wait 
    cout<<"in main thread, waiting for sub-thread to terminate"<<endl; 
    pthread_join(thread, NULL); 
    cout<<"in main thread, terminating"<<endl; 

    return EXIT_SUCCESS; 
} 

预期结果

  • 在主线程,等待子线程终止子线程
  • SIGALRM被抓到,回报
  • 主线程中,终止

把观察结果

    在主线程
  • ,等待子线程终止
  • 闹钟

附加信息: 我用G ++(Debian的5.4 .0-4)5.4.0 20160609.

+0

我怀疑这个问题的C++行为与C实现的不同。 @CherubimAnand – alk

+0

@CherubimAnand:我认为我会对搜索同一事物的人有用C – Immort

回答

1

run_something线程调用sigwait该信号,但this is undefined behavior前疏导SIGALRM。 sigwait从该组待定(即,阻止的)信号中去除信号。

不要在你的线程中解锁,你会看到你期望的行为。

+0

Sry,为了解答你的答案,把它翻了回来! – alk

+0

我希望添加/更新的sigwait()文档的链接:http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigwait.html – alk

+0

@alk,更新谢谢 – pilcrow

1

显示的代码没有设置任何sig最终处理程序为SIGARLM

因此,在接收信号时,操作系统应该如此,即调用SIGALRM's default action即终止进程。向控制台打印“闹钟”是默认行为的一部分,BTW。

要修复这个设置SIGARLM的信号处理程序。这可以通过使用sigaction()以便携式方式完成。


也不要在多线程程序中使用sigprocmask(),因为它的行为是不确定的。改为使用pthread_sigmask()


更新

我错过了代码调用sigwait() ...:}

在这种情况下解决这个问题并没有提高,需要建立一个信号处理器(仍也会解决问题并且是有效的),但是按照pilcrowanswer的提议进行操作,即在致电sigwait()(或sigwaitinfo())之前保留信号。

此外请确保使用pthread_sigmask()而不是sigprocmask()由于上述原因。


与问题无关的问题

创建主线程

一个子线程有没有这样的概念,如 “子” -threads。创建完成后,所有进程的线程都是同级的“同级”。这包括使用main()开始的初始线程。 “主” -thread通常被称为这种方式的线程函数的名称,只是因为:main

+0

我认为在main()函数的return()方法中,该进程退出并且所有线程都被终止。传递给'pthread_create()'的函数中的'return()'将简单地终止该线程。我觉得这是很重要的,因为我看过多少个问题,当用'main()'来启动线程,然后立即调用'return()'时,为什么一个进程突然终止。 –

+1

嗯,够公平的。但是,如果'main()'以'pthread_exit()'结尾,那么会有* no *差异。 @AndrewHenle – alk