1

My intention is to create a time out of 1 sec for fgets. If no input is received in 1 sec, then the program terminates.

The design I come up with is: the parent registers a signal handler for SIGALRM. Then it forks a child which will trigger SIGALRM and it goes ahead and call fgets. The SIGALRM will trigger the handler which kills the parent process. But when I execute this on a ubuntu 14.04 64-bit, the handler is not triggered and the program just waits for user to input for fgets forever.

Why would this happen and how can I fix this?

#include "csapp.h"                                                              

void handler() {                                                                
  printf("lazy man\n");                                                         
  kill(SIGKILL, getppid());                                                     
  exit(0);                                                                      
}                                                                               

int main() {                                                                    
  char buf[100];                                                                
  signal(SIGALRM, handler);                                                     
  pid_t pid;                                                                    
  if ((pid = fork()) == 0) {                                                    
    alarm(1);                                                                   
  } else {                                                                      
    fgets(buf, 100, stdin);                                                     
    printf("%s", buf);                                                          
  }                                                                             
  return 0;                                                                     
}      

~

drdot
  • 3,215
  • 9
  • 46
  • 81

2 Answers2

1

This forking and killing seems wrong. Just set the alarm, register an empty signal handler for SIGALRM, and then check the return value from fgets() - if it fails, check whether errno == EINTR; if it does - it was interrupted by signal.

0

If you will take time to read the manual of kill(), you will see that you miss the order of the arguments.

int kill(pid_t pid, int sig);

Fix:

kill(getppid(), SIGKILL); 

Plus, your child terminate his execution before that the signal is raise you must add a sleep() after your call to alarm() to make it wait:

alarm(1);
sleep(2);

Finally, printf() is not safe in a signal handler, list of safe function.

Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • 1
    Thank you for the suggestions! I have a design question: to achive this time out feature, is there other way to design this program instead of using kill? It makes the program unstable. Even after applying your fix, the program behaves as what I want. But sometimes the system just logout automatically. I think the way I used kill brings some unstability. – drdot Jun 04 '17 at 03:46
  • I will create another question. But i will take your solution for this one based on exiting design. – drdot Jun 04 '17 at 03:52
  • 1
    But I cannot agree on the annoying part. I do not know the kill will automatically log me out from the system. If you really want to hammer on this. Can you give an explanation? So rather than bothering with some mysterious system level stuff. I would rather spend time to create a proper design. But I am open to insights to this logout problem. – drdot Jun 04 '17 at 03:53
  • Here it is my friend and thank you very much for the answers :) https://stackoverflow.com/questions/44350650/create-a-timeout-for-fgets-in-c – drdot Jun 04 '17 at 04:00
  • Actually. I create a bash script to keep running the updated program. It does not automatically logout now. I am not sure why it has this problem before. – drdot Jun 04 '17 at 04:13