0

In a C++ multi-thread program, if multiple threads crash at the same time, the SIGABRT signal is triggered, but I want to do only once signal processing to print the error message and then exit, how should I deal with it?

I tried to use sigaction(), but after testing I found that the signal processing function still entered at the same time in different threads, the test code is below:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <atomic>
#include <sys/syscall.h>

#define gettid() syscall(__NR_gettid)
#define THREAD_NUM 10


int Signal(int signo,void (*func)(int))
{
    struct sigaction act;
    act.sa_handler = func;
    sigemptyset(&act.sa_mask);  
    sigaddset(&act.sa_mask, SIGABRT);
    sigaddset(&act.sa_mask, SIGBUS);
    sigaddset(&act.sa_mask, SIGSEGV);
    sigaddset(&act.sa_mask, SIGILL);
    sigaddset(&act.sa_mask, SIGFPE);

    act.sa_flags = 0;
    return sigaction(signo,&act,NULL);
}
void SigHandler(int Signal){
    printf("tid: %ld, access signal: %d\n", gettid(), Signal);
    sleep(3);
    _exit(1);
}

void* worker(void* args){
    for(;;){
        int a = std::stoi("");
    }
}

int main(){
    Signal(SIGBUS, SigHandler);  // 10 Core  Bus error (bad memory access)
    Signal(SIGSEGV, SigHandler); // 11 Core  Invalid memory reference
    Signal(SIGABRT, SigHandler); // 6  Core  Abort signal from abort(3)
    Signal(SIGILL, SigHandler);  // 4  Core  Illegal Instruction
    Signal(SIGFPE, SigHandler);  // 8  Core  Floating point exception
    // multi thread
    pthread_t pids[10];
    for(int i = 0; i < THREAD_NUM; i++){
        int err = pthread_create(&pids[i], NULL, worker, NULL);
        if(err != 0){
            perror("pthread_create err");
            return -1;
        }
    }
    for(int i = 0; i < THREAD_NUM; i++){
        pthread_join(pids[i], NULL);
    }
    return 0;
}

I compile the code by g++ test_sto.cpp -g -Wall -std=c++11 -lpthread -o test_sto.

the output is below:

terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi
tid: 1652380, access signal: 6
terminate called recursively
tid: 1652382, access signal: 6
terminate called recursively
tid: 1652384, access signal: 6
terminate called recursively
tid: 1652386, access signal: 6
terminate called recursively
tid: 1652378, access signal: 6
terminate called recursively
tid: 1652381, access signal: 6
terminate called recursively
tid: 1652383, access signal: 6
terminate called recursively
tid: 1652385, access signal: 6
terminate called recursively
tid: 1652379, access signal: 6
terminate called recursively
tid: 1652377, access signal: 6

In a multi-thread program, how do I mask the specified signal in signal processing?

  • 1
    Why is there a `sleep(3);` in `SigHandler` ? – Richard Critten Jul 19 '22 at 09:48
  • 1
    Use an atomic variable to guard handler execution. – n. m. could be an AI Jul 19 '22 at 09:58
  • In order to simulate slow operations in signal processing, such as printing the stack@RichardCritten – Karate Yuan Jul 19 '22 at 09:58
  • Signals handlers should really try to be as quick as possible, you shouldn't do heavy processing in them. Better just set a flag, and let the main process handle the heavy processing. Some signals are one-shot only, meaning there won't be a queue of signals until the current signal handler for the signal is finished. – Some programmer dude Jul 19 '22 at 10:16
  • Also, most signals are thread agnostic, meaning there's no telling which exact thread might get the signal raised. – Some programmer dude Jul 19 '22 at 10:18
  • 2
    In C++, even if one execution thread crashes with a `SIGABRT`, that's undefined behavior, and the state of the entire process is unknown, undefined, and cannot be relied to in any meaningful way. Attempting to recover from that, in some sort or fashion, using some sort of a concocted signal handler is equivalent to attempting to piece together a drivable car after it slammed into a brick wall at 100 mph. Even if one headlight is undamaged, the whole thing is gone. – Sam Varshavchik Jul 19 '22 at 11:04
  • 1
    POSIX signals work decently well with POSIX threads., in POSIX C code. The problem seems to be the small bit of C++. When you're writing C++, use `std::thread`. Use [`std::exception_ptr`](https://stackoverflow.com/questions/233127/how-can-i-propagate-exceptions-between-threads) to return exceptions from a `std::thread` – MSalters Jul 19 '22 at 11:14

0 Answers0