Reputation: 23
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
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