sbstnssndn
sbstnssndn

Reputation: 165

How to stop reading from keyboard once a signal is handled?

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?

Upvotes: 2

Views: 2559

Answers (3)

debuti
debuti

Reputation: 683

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

Upvotes: 1

Ben Voigt
Ben Voigt

Reputation: 283614

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.

Upvotes: 3

Rajeshkumar
Rajeshkumar

Reputation: 798

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)

Upvotes: 0

Related Questions