0

I know scanf waits for input. But in this program I have written it is printing hello in an infinite loop. Its not waiting for me to enter.

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include<unistd.h>

void timer_handler (int signum)
{
 static int count = 0;
 printf ("timer expired %d times\n", ++count);
}

int main ()
{
 struct sigaction sa;
 struct itimerval timer;


 memset (&sa, 0, sizeof (sa));
 sa.sa_handler = &timer_handler;
 sigaction (SIGALRM, &sa, NULL);


 timer.it_value.tv_sec = 0;
 timer.it_value.tv_usec = 250000;
 /* ... and every 250 msec after that. */
 timer.it_interval.tv_sec = 1;
 timer.it_interval.tv_usec = 250000;
 /* Start a virtual timer. It counts down whenever this process is
   executing. */
 setitimer (ITIMER_REAL, &timer, NULL);

 /* Do busy work. 
 */
 int i=0;
 while(1){
    scanf("%d",&i);      //****Not waiting for input****
    printf("hello");   
}
}

Output :

timer expired 1 times
hello timer expired 2 times
hello timer expired 3 times
hello timer expired 4 times
hello timer expired 5 times
hello timer expired 6 times
hello timer expired 7 times

Why ?

?

Aditya Jha
  • 69
  • 1
  • 8

1 Answers1

4

The scanf function on POSIX platforms somewhere in its implementation is using the read system call. When the timer signal is happening then the read call will be interrupted and return with an error (EINTR), which in turn leads to scanf returning as well. You can check this by checking what scanf returns. In this case it should return EOF with errno still set to EINTR.

A simple solution to this is to ask the signal to restart the interrupted system call. This is done by adding the SA_RESTART flag in the sigaction structures sa_flags member:

sa.sa_flags = SA_RESTART;

More information can be found in e.g. this POSIX sigaction reference.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • What is "*it*"? Signals *interrupt* your program, they have nothing to do with threads. –  Jul 20 '17 at 11:21