I'm writing a program where the SIGINT signal is handled the first time it is sent, but set to default after that. So, for example, I have this:
static volatile int stop_terminating = 1;
void handler(int dummy) {
stop_terminating = 0;
}
int main(){
signal(SIGINT, handler);
char input[256];
while(1){
if(stop_terminating == 0){
// reset the action of the signal to default
signal(SIGINT, SIG_DFL);
printf("Message sent.\n");
// increment counter so it doesn't enter this condition again
stop_terminating++;
}
printf("User input:\n");
fgets(input, sizeof(input), stdin);
// In this stage, I wanna press CTRL+C and print a message, stopping the fgets
// but what happens is: I press CTRL+C, the signal is catched, but fgets
// is still asking for an input, and after I send something, the my message is printed
// because it looped through the while(1) again.
}
}
How can I stop fgets from asking for an input and just print the message and then ask again for an input?
The Linux manual page for signals says that
Interruption of system calls and library functions by signal handlers
If a signal handler is invoked while a system call or library function call is blocked, then either:
the call is automatically restarted after the signal handler returns; or
the call fails with the error
EINTR
.Which of these two behaviors occurs depends on the interface and whether or not the signal handler was established using the
SA_RESTART
flag (seesigaction
(2)).
You may use either the siginterrupt()
function together with signal()
, or use sigaction()
instead of signal()
for registering your signal handler, in order to disable restarting a read()
system call after a signal.
Note however that fgets()
from the C library might call read()
multiple times until a newline character is found, therefore you may also need to switch to using the lower-level functions instead of stdio.h
APIs.