信号处理程序中的pthread_exit会导致分段错误

时间:2011-06-16 10:29:22

标签: linux pthreads segmentation-fault signals

下面的程序为整个过程设置SIG_ALRM处理程序,创建一个线程,将SIG_ALRM信号发送到新创建的线程。 在SIG_ALRM处理程序中调用pthread_exit。 结果 - 分段错误。 如果你在发送信号前睡觉 - 好的。

看起来pthread_exit时尚未启动新线程。 我尝试使用gdb找到分段错误,但无法使用gdb重现崩溃。

什么原因导致分段错误?

谢谢!

#include <signal.h>
#include <pthread.h>
#include <iostream>
#include <cassert>
using namespace std;

void* threadFunc(void* arg) {
    cout << "thread: started. sleeping..: " << pthread_self() << endl;
    sleep(10);
    cout << "thread: exit" << endl;
    return NULL;
}

void alrm_handler(int signo) {
    cout << "alrm_handler: " << pthread_self() << endl;

    pthread_exit(NULL); //if comment - no segmentation fault
}

int main() {
    cout << "main: " << pthread_self() << endl;

    struct sigaction act;
    act.sa_handler = alrm_handler;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    sigaction(SIGALRM, &act, NULL);

    pthread_t t;
    int rc = pthread_create(&t, NULL, threadFunc, NULL);
    assert(rc == 0);

//  usleep(1000); //if Uncomment - no segmentation fault
    rc = pthread_kill(t, SIGALRM);
    assert(rc == 0);

    pthread_join(t, NULL);

    cout << "main: exit" << endl;
    return 0;
}

输出:

  

主要:140130531731232
  alrm_handler:140130504095488
  分段错误

2 个答案:

答案 0 :(得分:4)

pthread_exit不是异步信号安全的。除非可以确定信号处理程序没有中断异步信号不安全功能,否则不能从信号处理程序调用它。特别是,调用pthread_create和新线程的启动函数之间的时间必须被视为async-signal-unsafe - 这在标准中从未明确说明,但您可以将新线程视为静止如果你愿意,可以“在pthread_create”(这是异步信号不安全的)。

答案 1 :(得分:1)

更改线程初始化进程以完成。所以只是取消注释下面的行是正确的方法。

  usleep(1000);