EdgarC
EdgarC

Reputation: 23

SIGINT singal is being catched only once

Here's a simple recreation of this issue:

void handler(int sig){
        if(sig == SIGINT){
                printf("Signal caught\n");
                execl("./recreate","./recreate",NULL);
        }
}

int main(){
    printf("Main start\n");
    signal(SIGINT,handler);
    while(1);

        return 0;
}

It simply runs itself again after receiving the signal. What happens is that it is only able to read CTR+C from the terminal once. From the second point onward is simply writes ^C on the console. Do I need to reset the handler every time or something similar? Thanks in advance.

Upvotes: 0

Views: 555

Answers (1)

Petr Skocik
Petr Skocik

Reputation: 60068

signal is highly implementation defined and you should use sigaction because of that. What you're observing are the so-called sysv semantics of signal--the signal is reset in the handler to SIG_DFL and it's not blocked from reexecution.

You probably want something like:

#include <unistd.h>
#include <signal.h>
#include <stdio.h>

#define WRITE_LIT(fd, lit) write(fd, lit, sizeof lit - 1)

void handler(int sig){
        if(sig == SIGINT){
            WRITE_LIT(2, "Signal caught\n");
            execl("./recreate","./recreate", (char*)NULL);
            WRITE_LIT(2, "Couldn't run ./recreate\n");
            _exit(127);
        }
}

int main(){
    printf("Main start\n");
    sigaction(SIGINT, &(struct sigaction const){ 
        .sa_handler = handler, 
        .sa_flags = SA_NODEFER /*don't block signals for the new process image*/
    },
    0);
    while(1);
        return 0;
}

This won't reset the signal and it won't block it either (the default is to block it for the duration of the handler) because the new process image likely won't want it blocked.

Upvotes: 2

Related Questions