Timeout Function - c

I want to make a code in which Name of User will be asked to input, but in a time limit of 15 seconds. If user cross the limit & failed to input a name(or any string), then code will be terminated & "Time Out" Massage will be display otherwise Name should be saved & "Thanks" massage will be display. I had try like this but it's wrong & not working. Please give me a solution for this.. Thanks.
#include <stdio.h>
#include <time.h>
int timeout ( int seconds )
{
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
return 1;
}
int main ()
{
char name[20];
printf("Enter Username: (in 15 seconds)\n");
printf("Time start now!!!\n");
scanf("%s",name);
if( timeout(5) == 1 ){
printf("Time Out\n");
return 0;
}
printf("Thnaks\n");
return 0;
}

Probably this dummy program might help you:
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#define WAIT 3
int main ()
{
char name[20] = {0}; // in case of single character input
fd_set input_set;
struct timeval timeout;
int ready_for_reading = 0;
int read_bytes = 0;
/* Empty the FD Set */
FD_ZERO(&input_set );
/* Listen to the input descriptor */
FD_SET(STDIN_FILENO, &input_set);
/* Waiting for some seconds */
timeout.tv_sec = WAIT; // WAIT seconds
timeout.tv_usec = 0; // 0 milliseconds
/* Invitation for the user to write something */
printf("Enter Username: (in %d seconds)\n", WAIT);
printf("Time start now!!!\n");
/* Listening for input stream for any activity */
ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
/* Here, first parameter is number of FDs in the set,
* second is our FD set for reading,
* third is the FD set in which any write activity needs to updated,
* which is not required in this case.
* Fourth is timeout
*/
if (ready_for_reading == -1) {
/* Some error has occured in input */
printf("Unable to read your input\n");
return -1;
}
if (ready_for_reading) {
read_bytes = read(0, name, 19);
if(name[read_bytes-1]=='\n'){
--read_bytes;
name[read_bytes]='\0';
}
if(read_bytes==0){
printf("You just hit enter\n");
} else {
printf("Read, %d bytes from input : %s \n", read_bytes, name);
}
} else {
printf(" %d Seconds are over - no data input \n", WAIT);
}
return 0;
}
Update:
This is now tested code.
Also, I have taken hints from man for select. This manual already contains a code snippet which is being used to read from the terminal and timeout in 5 seconds in case of no activity.
Just a brief explanation in case the code is not well written enough:
We add the input stream (fd = 1) to the FD set.
We initiate select call to listen to this FD set created for
any activity.
In case any activity occurs within the timeout period, that is
read through the read call.
In case there was no activity, timeout occurs.
Hope this helps.

scanf() is not the best function to get an input in a limited time frame.
Instead I would build a specific input function around select() (for managing timeout) and read() (for getting input) system calls.

One thing you have to think about, is that you have a single thread of execution in your program. As such, the timeout function will only be called when the scanf function will be terminated. This is not what you want.
One way to do this task, is to use the select function. It waits for a potentially limited amount of time (your timeout) for availability of input on some file descriptors (stdin for you).

Related

How to start counting 5 seconds before exiting from program?

I've been pulling my hair out on this for many hours now. Basically, I have a program that asks the user to enter his password (123), and if the user doesn't enter anything for 5 seconds then the program will exit (game over). I've been trying to use time(NULL) and clock() but still no luck. Can anyone point me in the right direction, please? Thanks a lot in advance!
Here's my code:
#include <stdio.h>
#include <time.h>
int main(){
int password = 0;
int num = 0;
printf("%s\n", "Please enter your password");
scanf("%d", &password);
// Here I need to check if user didnt enter anything for 5 seconds,
// and if he didnt enter anything then exit out of the program
// I tried using time
// time_t start = time(NULL);
// time_t stop = time(NULL);
// if(((stop - start) * 1000) > 5000){
// printf("%s\n", "Game Over");
// break;
// }
printf("%s\n", "Thank you for entering your password, now enter any number");
scanf("%d", &num);
return 0;
}
Your main challenge is that scanf() - as well as getchar() and similar commands - are blocking. An unknown interval of time could elapse before the user actually enters any input - and your five seconds might already be up at that stage.
select() - monitor file descriptors with timeout
I think one of the most feasible options is to use select() - which monitors for activity on certain sets of file descriptors. Specifically, you want to monitor for activity on the stdin file descriptor.
The following accomplishes something close to what you need I believe.
#include <stdio.h>
#include <sys/select.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
int main(void) {
char buf[16] = {'\0'};
char *pass = buf;
time_t time_update = 0, time_now = 0;
struct timeval tm;
int res = 0;
struct termios term_attr, new_attr;
fd_set rset;
// Change terminal attributes (We don't want line-buffered mode.)
tcgetattr(fileno(stdin), &term_attr);
tcgetattr(fileno(stdin), &new_attr);
new_attr.c_lflag &= ~(ICANON | ECHO);
tcsetattr(fileno(stdin), TCSANOW, &new_attr);
printf("Enter password: ");
time_update = time(NULL);
while (1) {
tm.tv_sec = 0;
tm.tv_usec = 50000;
FD_ZERO(&rset);
FD_SET(STDIN_FILENO, &rset);
res = select(fileno(stdin) + 1, &rset, NULL, NULL, &tm);
if (FD_ISSET(STDIN_FILENO, &rset)) {
time_update = time(NULL);
int c = getchar();
if (c == '\n') {
break;
}
*pass = c;
pass++;
}
time_now = time(NULL);
if (time_now - time_update >= 5) {
puts("Timed out ...");
break;
}
}
pass = buf;
printf("You entered: %s \n", pass);
// Restore original terminal attributes
tcsetattr(fileno(stdin), TCSANOW, &term_attr);
return 0;
}
Notes:
The last argument to select() is a struct timeval which specifies how long to wait for activity on the specified file descriptors. In this case I have specified a timeout of 50 milliseconds.
The terminal needs to be placed in character buffer mode rather than line-buffered mode. (Otherwise you will need to press enter every time there is a new character.)
Operating system support
select() is part of the POSIX specification, but I do not know if it is implemented on Windows. Maybe someone can clarify?
Also ... I do not know if setting the terminal attributes will work as expected on Windows either. (I have only tested on Linux.)
I realize this solution might be a little longer / more complex than you hoped - but I am not aware of an easier way.

How can I prevent scanf() to wait forever for an input character?

I want to fulfill the following things in a console application:
If user inputs a character, the application will do the
corresponding task. For example, if user inputs 1, the program
will do task 1, if user inputs q, the program will quit;
If user inputs nothing, the program will do the default task every 10 seconds (the time needn't to be very strict).
Here is my code:
#include <stdio.h>
#include <time.h>
char buff[64];
char command;
while(command != 'q')
{
begin:
printf(">> ");
scanf("%s", buff);
command = buff[0];
switch (command)
{
case '1':
// task 1 code will be added here;
break;
case '2':
// task 2 code will be added here;
break;
case 'q':
printf("quit the loop.\n");
break;
}
// wait for 10 seconds;
Sleep(10000);
// default task code will be added here;
if(command != 'q')
{
goto begin;
}
}
But the problem is the program will trap at the line of scanf() function forever to wait for an input character, if no character is entered. So I'm wondering how to skip the line of scanf() after a certain time, I mean for example, if no input after 1 second, the program can continue, so as to fulfill the second thing listed above.
The platform is Windows, if it matters.
I've removed the semicolon after the while() it was an obvious mistake.
Try using the select() function. Then you can wait for 10 seconds until you can read from stdin without blocking. If select() returns with zero, perform the default action.
I don't know if this works on windows, it's POSIX standard. If you happen to develop on unix/linux, try man select
I just wrote a working example using select:
#include <stdlib.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define MAXBYTES 80
int main(int argc, char *argv[])
{
fd_set readfds;
int num_readable;
struct timeval tv;
int num_bytes;
char buf[MAXBYTES];
int fd_stdin;
fd_stdin = fileno(stdin);
while(1) {
FD_ZERO(&readfds);
FD_SET(fileno(stdin), &readfds);
tv.tv_sec = 10;
tv.tv_usec = 0;
printf("Enter command: ");
fflush(stdout);
num_readable = select(fd_stdin + 1, &readfds, NULL, NULL, &tv);
if (num_readable == -1) {
fprintf(stderr, "\nError in select : %s\n", strerror(errno));
exit(1);
}
if (num_readable == 0) {
printf("\nPerforming default action after 10 seconds\n");
break; /* since I don't want to test forever */
} else {
num_bytes = read(fd_stdin, buf, MAXBYTES);
if (num_bytes < 0) {
fprintf(stderr, "\nError on read : %s\n", strerror(errno));
exit(1);
}
/* process command, maybe by sscanf */
printf("\nRead %d bytes\n", num_bytes);
break; /* to terminate loop, since I don't process anything */
}
}
return 0;
}
Note: the poll() example below is OK too, no problem. For the rest I chose to read the available bytes into a buffer (up to MAXBYTES). It can be (s)scanned afterwards. (scanf() just isn't too much my friend, but that's a personal taste matter).
Here is a working example of how to do this with poll (probably the most 'correct' way on Linux):
#include <unistd.h>
#include <poll.h>
#include <stdio.h>
int main()
{
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
char string[10];
if( poll(&mypoll, 1, 2000) )
{
scanf("%9s", string);
printf("Read string - %s\n", string);
}
else
{
puts("Read nothing");
}
return 0;
}
The timeout is the third argument to poll and is in milliseconds - this example will wait for 2 seconds for input on stdin. Windows has WSAPoll, which should work similarly.
But the problem is the program will trap at the line of scanf() function forever to wait for an input character,
Remove the semicolon after while.
Try alarm(3)
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char buf [10];
alarm(3);
scanf("%s", buf);
return 0;
}
As others have said, the best way to do truly async IO is with select(...).
But a quick and dirty way to do what you want is with getline(...) which will return the number of bytes read every time (not hanging on IO) and returns -1 on no bytes read.
The following is from the getline(3) man page:
// The following code fragment reads lines from a file and writes them to standard output.
// The fwrite() function is used in case the line contains embedded NUL characters.
char *line = NULL;
size_t linecap = 0;
ssize_t linelen;
while ((linelen = getline(&line, &linecap, fp)) > 0)
fwrite(line, linelen, 1, stdout);
Unfortunately, what you are asking for is not possible in plain ISO C. However, most platforms offer platform-specific extensions which provide the functionality that you require.
Since you stated that your question applies to Microsoft Windows, the two functions that you are looking for are WaitForSingleObject and ReadConsoleInput. You won't be able to use the function scanf or C-style streams (FILE*) for this.
The function WaitForSingleObject allows you to wait until a specific object is in a signalled state. It also allows you to set a timeout (which should be 10 seconds in your case).
One type of object that WaitForSingleObject can wait for is a console handle. It will be in a signalled state when there is new input available to be read by ReadConsoleInput. According to my tests, it won't work reliably with ReadConsole though, because even if WaitForSingleObject indicates that input is waiting, the function ReadConsole will still sometimes block. This is because in contrast to ReadConsoleInput, the function ReadConsole will filter some events. Therefore, attempting to read one event with ReadConsole may actually attempt to read more than one raw event, which will cause the function to block if there are no non-filtered raw events available. The function ReadConsoleInput does not have this problem, as it works with raw events directly and does not filter any.
Here is my program which uses the functions mentioned above, and does exactly what you asked for.
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void DoDefaultTask()
{
printf( "Doing default task.\n" );
}
void DoTask1()
{
printf( "Doing task #1.\n" );
}
void DoTask2()
{
printf( "Doing task #2.\n" );
}
int main(void)
{
INPUT_RECORD ir;
HANDLE hConInput = GetStdHandle(STD_INPUT_HANDLE);
DWORD dwReadCount;
bool should_prompt = true, quit = false;
while ( !quit )
{
//prompt user for input
if ( should_prompt )
{
printf( "Please select an option: " );
should_prompt = false;
}
//flush output
fflush( stdout );
switch ( WaitForSingleObject( hConInput, 10000 ) )
{
case WAIT_OBJECT_0:
//attempt to read input
if ( !ReadConsoleInput( hConInput, &ir, 1, &dwReadCount ) || dwReadCount != 1 )
{
fprintf( stderr, "Unexpected input error!\n" );
exit( EXIT_FAILURE );
}
//only handle key-down events
if ( ir.EventType != KEY_EVENT || !ir.Event.KeyEvent.bKeyDown )
break;
//echo output, if character is printable
if ( isprint( (unsigned char)ir.Event.KeyEvent.uChar.AsciiChar ) )
{
printf( "%c", ir.Event.KeyEvent.uChar.AsciiChar );
}
printf( "\n" );
switch ( ir.Event.KeyEvent.uChar.AsciiChar )
{
case '1':
DoTask1();
break;
case '2':
DoTask2();
break;
case 'q':
printf( "Quitting program...\n" );
quit = true;
break;
default:
printf( "Unknown command.\n" );
}
should_prompt = true;
break;
case WAIT_TIMEOUT:
printf( "Timeout!\n" );
DoDefaultTask();
should_prompt = true;
break;
default:
fprintf( stderr, "unexpected error!" );
exit( EXIT_FAILURE );
}
}
return 0;
}
This program has the following behavior:
Please select an option: 1
Doing task #1.
Please select an option: 2
Doing task #2.
Please select an option: 3
Unknown command.
Please select an option: 4
Unknown command.
Please select an option: Timeout!
Doing default task.
Please select an option: Timeout!
Doing default task.
Please select an option: 1
Doing task #1.
Please select an option: 3
Unknown command.
Please select an option: 2
Doing task #2.
Please select an option: 1
Doing task #1.
Please select an option: Timeout!
Doing default task.
Please select an option: q
Quitting program...

Why is this message not only displayed when a file is written to (using the poll C Linux function)?

I was reading about poll in C programming and built an application given on the poll(2) man page.
Here is the example:
#include<stdio.h>
#include <stropts.h>
#include <poll.h>
#include <fcntl.h>
int main() {
struct pollfd fds[2];
int timeout_msecs = -1;
int ret;
int i;
/* Open STREAMS device. */
fds[0].fd = open("/home/jeshwanth/mywork/poll/dev0", O_RDONLY);
fds[1].fd = open("/home/jeshwanth/mywork/poll/dev1", O_RDONLY);
fds[0].events = POLLOUT | POLLWRBAND;
fds[1].events = POLLOUT | POLLWRBAND;
while (1) {
ret = poll(fds, 2, timeout_msecs);
if (ret > 0) {
/* An event on one of the fds has occurred. */
for (i = 0; i < 2; i++) {
if (fds[i].revents != 0) {
/* Priority data may be written on device number i. */
printf(
"Priority Data may be written on device number %d POLLWRBAND\n",
i);
}
if (fds[i].revents = !0) {
/* Data may be written on device number i. */
printf("Data may be written on device number %d POLLOUT\n",
i);
}
if (fds[i].revents = !0) {
/* A hangup has occurred on device number i. */
printf("A hangup has occurred on device number %d\n", i);
}
}
}
}
return 0;
}
Note: dev0 and dev1 are normal files. When I run the program, if no event occurred in dev0 and dev1, the message is displayed. But I was expecting when some write into the file happens, only then should it display the message. Am I wrong?
Polling it for output readiness doesn't mean you will get notified when some output occurs: it means that you'll get notified when there is output buffer space available so you can output (but you should still check the return value of your output function. The buffer state may have changed between polling and outputting; always check return values).
Minimal FIFO named pipe example
You won't be able to see anything interesting with regular files, since those always give POLLIN immediately: How can select() wait on regular file descriptors (non-sockets)?
The simplest way to play around with poll is to use named pipes as shown below. This should prepare you for their major application: sockets and device files.
Source below. Usage:
sudo mknod poll0.tmp p
sudo mknod poll1.tmp p
sudo chmod 666 poll*.tmp
./poll.out
On another shell:
printf a > poll0.tmp
printf b > poll1.tmp
Output:
loop
POLLIN i=0 n=1 buf=a
loop
POLLHUP i=0
loop
POLLIN i=1 n=1 buf=b
POLLHUP i=1
loop
So notice how poll waits for the reads without looping.
Cooler example:
(while true; do date; sleep 1; done) > poll0.tmp &
(while true; do date; sleep 2; done) > poll1.tmp &
0 gets written every one second, and 1 every two seconds, which shows how poll() is dealing with both inputs concurrently, without stalling each other.
Source:
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
enum { N = 2 };
char buf[1024], path[1024];
int fd, i, n;
short revents;
struct pollfd pfds[N];
for (i = 0; i < N; ++i) {
snprintf(path, sizeof(path), "poll%d.tmp", i);
/* O_NONBLOCK is required or else the open blocks
* until the other side of the pipe opens. */
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
pfds[i].fd = fd;
/* Only events in this mask will be listened to.
* However, there are also some events that are unmaskable,
* notably POLLHUP when pipe closes! */
pfds[i].events = POLLIN;
}
while (1) {
puts("loop");
i = poll(pfds, N, -1);
if (i == -1) {
perror("poll");
exit(EXIT_FAILURE);
}
for (i = 0; i < N; ++i) {
revents = pfds[i].revents;
if (revents & POLLIN) {
n = read(pfds[i].fd, buf, sizeof(buf));
printf("POLLIN i=%d n=%d buf=%.*s\n", i, n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP i=%d\n", i);
/* This happens when the other side closed.
* This event is only cleared when we close the reader. */
/* poll won't set POLLHUP anymore once all fds are closed.
* Any futher polls on this will give the POLLNVAL event instead. */
close(pfds[i].fd);
/* negative fds are ignored. So if we negate an FD,
* we can both turn if off for a while, and turn it on
* later on by re-nagating it. */
pfds[i].fd *= -1;
}
}
}
}
Compile with:
gcc -o poll.out -std=c99 poll.c
Tested in Ubuntu 14.04.
GitHub upstream.
The lines:
close(pfds[i].fd);
pfds[i].fd *= -1;
are required or else you get POLLHUP forever, see also: How to use the poll C function to watch named pipes in Linux?
For even more fun, create a Linux kernel module what implements the poll fops: How to add poll function to the kernel module code?
I'll give you a hint on how to correct it. revents is interpreted as several bit flags.
/* check for priority write readiness */
if (fds[i].revents & POLLWRBAND) {
printf("Priority Data may be written on device number %d POLLWRBAND\n", i);
}
/* check for write readiness */
if (fds[i].revents & POLLOUT) {
printf("Data may be written on device number %d POLLOUT\n", i);
}
/* check for hang-up */
if (fds[i].revents & POLLHUP) {
printf("A hangup has occurred on device number %d\n", i);
}

How to loop select() to poll for data ad infinitum

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
int main ()
{
char name[20];
fd_set input_set;
struct timeval timeout;
int ready_for_reading = 0;
int read_bytes = 0;
/* Empty the FD Set */
FD_ZERO(&input_set );
/* Listen to the input descriptor */
FD_SET(0, &input_set);
/* Waiting for some seconds */
timeout.tv_sec = 10; // 10 seconds
timeout.tv_usec = 0; // 0 milliseconds
/* Invitation for the user to write something */
printf("Enter Username: (in 15 seconds)\n");
printf("Time start now!!!\n");
/* Listening for input stream for any activity */
ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
/* Here, first parameter is value of the socket descriptor + 1 (STDIN descriptor is 0, so
* 0 +1 = 1)
* in the set, second is our FD set for reading,
* third is the FD set in which any write activity needs to updated, which is not required
* in this case. Fourth is timeout
*/
if (ready_for_reading == -1) {
/* Some error has occured in input */
printf("Unable to read your input\n");
return -1;
} else {
if (ready_for_reading) {
read_bytes = read(0, name, 19);
printf("Read, %d bytes from input : %s \n", read_bytes, name);
} else {
printf(" 10 Seconds are over - no data input \n");
}
}
return 0;
}
How to do the same, but not just once, but in infinite loop which breaks after encountering 'quit' string (for example). Every way I tried - failed.
So if no data has been inputed after 10 seconds program just prints "10 secs are over - no data input" and then starts waiting again. Same after input - just begins again and behave the same every time in infinite loop.
Am little desperate already, please - help.
Thanks.
I don't really see the problem here. Basically just put everything you want in the loop, and let it run. Did you try this?
int main ()
{
/* Declarations and stuff */
/* ... */
/* The loop */
int break_condition = 0;
while (!break_condition)
{
/* Selection */
FD_ZERO(&input_set ); /* Empty the FD Set */
FD_SET(0, &input_set); /* Listen to the input descriptor */
ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
/* Selection handling */
if (ready_for_reading)
{
/* Do something clever with the input */
}
else
{
/* Handle the error */
}
/* Test the breaking condition */
break_condition = some_calculation();
}
return 0;
}
Note that you have to have keep resetting the selection inside the loop so that it will respond again in the next iteration.
The select() function can be told to block indefinitely by setting timeout to NULL. See select(2) man page:
timeout is an upper bound on the amount of time elapsed before select() returns. If both fields of the timeval stucture are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.
So what you want is:
...
ready_for_reading = select(1, &input_set, NULL, NULL, NULL);
...

How can I implement timeout for read() when reading from a serial port (C/C++)

I am reading bytes from a serial port in C++ using a file descriptor and the posix/unix read() function. In this example, I am reading 1 byte from the serial port (baud rate settings and similiar are omitted for clarity):
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
char buf[1];
int bytesRead = read(fd, buf, 1);
close(fd);
return 0;
}
If the device connected to /dev/ttyS0 does not send any information, the program will hang. How can I set a timeout?
I have tried setting a time out like this:
struct termios options;
tcgetattr(fd, &options);
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;
tcsetattr(fd, TCSANOW, &options);
I thought it was supposed to give 1 second timeout, but it makes no difference. I think I have misunderstood VMIN and VTIME. What is VMIN and VTIME used for?
Then I searched the web and found somebody talking about the select() function. Is that the solution and if so, how would one apply that to the program above to make 1 second timeout?
Any help is appreciated. Thanks in advance :-)
Yes, use select(2). Pass in a file descriptor set containing just your fd in the read set and empty write/exception sets, and pass in an appropriate timeout. For example:
int fd = open(...);
// Initialize file descriptor sets
fd_set read_fds, write_fds, except_fds;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);
FD_SET(fd, &read_fds);
// Set timeout to 1.0 seconds
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
// Wait for input to become ready or until the time out; the first parameter is
// 1 more than the largest file descriptor in any of the sets
if (select(fd + 1, &read_fds, &write_fds, &except_fds, &timeout) == 1)
{
// fd is ready for reading
}
else
{
// timeout or error
}
What is VMIN and VTIME used for?
If MIN > 0 and TIME = 0, MIN sets the number of characters to receive
before the read is satisfied. As TIME is zero, the timer is not used.
If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will
be satisfied if a single character is read, or TIME is exceeded (t =
TIME *0.1 s). If TIME is exceeded, no character will be returned.
If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The
read will be satisfied if MIN characters are received, or the time
between two characters exceeds TIME. The timer is restarted every time
a character is received and only becomes active after the first
character has been received.
If MIN = 0 and TIME = 0, read will be satisfied immediately. The
number of characters currently available, or the number of characters
requested will be returned. According to Antonino (see contributions),
you could issue a fcntl(fd, F_SETFL, FNDELAY); before reading to get
the same result.
Source : http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html
You can attempt capture signal to stop read operation. use alarm(1) before read, and if read function did not returned, alarm will send SIGALRM signal, then you can create signal processing function to capture this signal, like this:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
static jmp_buf env_alarm;
static void sig_alarm(int signo)
{
longjmp(env_alarm, 1);
}
int main(void)
{
int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);
char buf[1];
if (signal(SIGALRM, sig_alarm) == SIG_ERR)
{
exit(0);
}
if (setjmp(env_alarm) != 0)
{
close(fd);
printf("Timeout Or Error\n");
exit(0);
}
alarm(1);
int bytesRead = read(fd, buf, 1);
alarm(0);
close(fd);
return 0;
}
But use select or poll or epoll will be better if your program is big.
select() is the way I would solve this problem.
There are several pages on the internet that will give info on how to use select(), such as http://www.unixguide.net/unix/programming/2.1.1.shtml
There are several possible approaches. If the program will eventually be timing more than one i/o operation, select() is the clear choice.
However, if the only input is from this i/o, then selecting non-blocking i/o and timing is a straightforward method. I have expanded it from single character i/o to multi-character to make it a more generally complete example:
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/time.h>
int main(void)
{
int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY); // sometimes "O_NONBLOCK"
char buf[10];
int done = 0, inbuf = 0;
struct timeval start, now;
gettimeofday (&start, NULL);
while (!done)
{
int bytesRead = read(fd, &buf[inbuf], sizeof buf - inbuf);
if (bytesRead < 0)
{
error_processing_here();
continue;
}
if (bytesRead == 0) // no data read to read
{
gettimeofday (&now, NULL);
if ((now.tv.sec - start.tv_sec) * 1000000 +
now.tv.usec - start.tv_usec > timeout_value_in_microsecs)
{
done = 2; // timeout
continue;
}
sleep(1); // not timed out yet, sleep a second
continue;
}
inbuf += bytesRead;
if (we have read all we want)
done = 1;
}
if (done == 2)
timeout_condition_handling();
close(fd);
return 0;
}

Resources