Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set a timeout for reading stdin

Tags:

c

posix

Is there a way to timeout a reading from stdin in order for the program not to hang for too long ?

read(0, var, numberofbytes);
like image 903
Neeladri Vishweswaran Avatar asked Sep 14 '10 18:09

Neeladri Vishweswaran


Video Answer


2 Answers

You can use ncurses or if you don't want to, you can use select as described in this blog post. Basically, you can use select and specify the timeout. If the stdin FD is set, then you can read from it safely and won't block. If you want more info on select, check this out and of course wikipedia. It's a handy call to know about.

EDIT: I feel compelled to supply code, so here it is, straight from the blog post with some comments.

// if != 0, then there is data to be read on stdin
int kbhit()
{
    // timeout structure passed into select
    struct timeval tv;
    // fd_set passed into select
    fd_set fds;
    // Set up the timeout.  here we can wait for 1 second
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    // Zero out the fd_set - make sure it's pristine
    FD_ZERO(&fds);
    // Set the FD that we want to read
    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
    // select takes the last file descriptor value + 1 in the fdset to check,
    // the fdset for reads, writes, and errors.  We are only passing in reads.
    // the last parameter is the timeout.  select will return if an FD is ready or 
    // the timeout has occurred
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    // return 0 if STDIN is not ready to be read.
    return FD_ISSET(STDIN_FILENO, &fds);
}
like image 82
NG. Avatar answered Sep 23 '22 01:09

NG.


Use select, poll or any other IO multiplexing facility. They all take a timeout argument. Note that this will not work if stdin is a regular file, but it will if stdin is a terminal/tty,socket,pipe.

e.g.

fd_set selectset;
struct timeval timeout = {10,0}; //timeout of 10 secs.
int ret;
FD_ZERO(&selectset);
FD_SET(0,&selectset);
ret =  select(1,&selectset,NULL,NULL,&timeout);
if(ret == 0)
  //timeout
else if(ret == -1)
  //error
else 
   // stdin has data, read it
   // (we know stdin is readable, since we only asked for read events
   //and stdin is the only fd in our select set.
like image 27
nos Avatar answered Sep 25 '22 01:09

nos