pthread_exit в обработчике сигнала вызывает ошибку сегментации - PullRequest
2 голосов
/ 16 июня 2011

Программа ниже устанавливает обработчик 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;
}

Вывод:

main: 140130531731232
alrm_handler: 140130504095488
Ошибка сегментации

Ответы [ 2 ]

4 голосов
/ 12 июля 2011

pthread_exit не является безопасным для асинхронного сигнала. Вы не можете вызывать его из обработчиков сигналов, если не уверены, что обработчик сигналов не прерывает асинхронную небезопасную функцию. В частности, время между вызовом pthread_create и входом в функцию запуска вашего нового потока должно считаться небезопасным как асинхронный сигнал - в стандарте это явно не прописано, но вы можете думать о том, что новый поток все еще остается " в pthread_create "(что небезопасно при асинхронном сигнале), если хотите.

1 голос
/ 16 июня 2011

Дать изменение для потока инициализация процесс должен быть завершен. так что просто раскомментируйте нижеприведенную строку - правильный подход.

  usleep(1000); 
...