pthread_exit в обработчике сигнала вызывает ошибку сегментации

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

Решение

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

  usleep(1000); 

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

Другие вопросы по тегам