2

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?

sbstnssndn
  • 145
  • 1
  • 18

3 Answers3

3

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 (see sigaction(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.

Community
  • 1
  • 1
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

If you close stdin fgets will return immediately, then you can try to open stdin again. This is weird but can work as a workaround

debuti
  • 623
  • 2
  • 10
  • 20
0

You get a NULL from fgets when it reaches EOF. From the keyboard, that's usually signalled with CTRL-D (Linux/Unix/MacOS X) or CTRL-Z (DOS/Windows and I think MacOS before X)

Rajeshkumar
  • 739
  • 5
  • 16