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
" (что небезопасно при асинхронном сигнале), если хотите.