Using raise in GCD can cause timing issues with the signal mechanism.

when we use raise in GCD, the signal handler is executed asynchronously, whereas in pthread, it is executed synchronously as expected.

example:

#include <Foundation/Foundation.h>
#include <pthread/pthread.h>

static void HandleSignal(int sigNum, siginfo_t* signalInfo, void* userContext) {
    printf("handle signal %d\n", sigNum);
    printf("begin sleep\n");
    sleep(3);
    printf("end sleep\n");
}

void InstallSignal(void) {
    static const int g_fatalSignals[] =
    {
        SIGABRT,
        SIGBUS,
        SIGFPE,
        SIGILL,
        SIGPIPE,
        SIGSEGV,
        SIGSYS,
        SIGTRAP,
    };
    int fatalSignalsCount = sizeof(g_fatalSignals) / sizeof(int);
    struct sigaction action = {{0}};
    action.sa_flags = SA_SIGINFO | SA_ONSTACK;
#if defined(__LP64__)
    action.sa_flags |= SA_64REGSET;
#endif
    sigemptyset(&action.sa_mask);
    action.sa_sigaction = &HandleSignal;
    struct sigaction pre_sa;
    for(int i = 0; i < fatalSignalsCount; i++) {
        int sigResult = sigaction(g_fatalSignals[i], &action, &pre_sa);
    }
}

void* RaiseAbort(void *userdata) {
    raise(SIGABRT);
    printf("signal handler has finished\n");
    return NULL;
}

int main(int argc, const char * argv[]) {

    InstallSignal();

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        raise(SIGABRT);
        // abort(); // abort() is ok
        RaiseAbort(nullptr);
    });
    
    // pthread is ok
    // pthread_t tid;
    // int ret = pthread_create(&tid, NULL, RaiseAbort, NULL);
    // if (ret != 0) {
    //     fprintf(stderr, "create thread failed\n");
    //     return EXIT_FAILURE;
    // }
    [[NSRunLoop mainRunLoop] run];
    return 0;
}

console log:

signal handler has finished
handle signal 6
begin sleep
end sleep
Answered by DTS Engineer in 850673022

OK, let’s take a step back: What are you trying to do with signals?

It’s very hard to use signals correctly. That especially true if you’re doing this in a process that uses Apple frameworks. For example, the code you posted is illegal because it calls printf from an async signal handler, and printf is not an async signal safe function.

Most folks who ask about signal handlers are trying to implement a crash reporter. That’s impossible to do well. I talk about it in great depth in Implementing Your Own Crash Reporter.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

OK, let’s take a step back: What are you trying to do with signals?

It’s very hard to use signals correctly. That especially true if you’re doing this in a process that uses Apple frameworks. For example, the code you posted is illegal because it calls printf from an async signal handler, and printf is not an async signal safe function.

Most folks who ask about signal handlers are trying to implement a crash reporter. That’s impossible to do well. I talk about it in great depth in Implementing Your Own Crash Reporter.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Using raise in GCD can cause timing issues with the signal mechanism.
 
 
Q