I'm trying to use the select function to accept input but every 2 seconds do something else if the user hasn't entered anything. The code below is waiting two seconds the first time select() is reached but once it prints the first "timed out" message it rapidly keep printing out "timed out" without waiting for 2 seconds, basically entering an infinite loop. Anyone know what the problem is? Thanks for any help.
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
const int STDIN = 0;
int main(int argc, int *argv[])
{
struct timeval tv;
fd_set readfds, master;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&master);
FD_SET(STDIN, &readfds);
FD_SET(STDIN, &master);
string buffer = "";
while(buffer != "quit"){
readfds = master;
if(select(STDIN+1, &readfds, NULL, NULL, &tv) == -1) perror("select");
if (FD_ISSET(STDIN, &readfds)){
getline(cin, buffer);
cout << "You entered: " << buffer << endl;
}else
cout << "Timed out.\n" << endl;
}
return 0;
}
per man: select() may update the timeout argument to indicate how much time was left. pselect() does not change this argument.
This implies that if it times out after 2 seconds it could set your tv_sec to 0.
If both of the fields of timeval are 0 it will return immediately.
Try setting your timeout every loop inside the while() to insure it's not getting overwritten.
I do some change based on your code, after select tv will be changed.
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
using namespace std;
const int STDIN = 0;
int main(int argc, int *argv[])
{
struct timeval tv,tv1;
fd_set readfds, master;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&master);
FD_SET(STDIN, &readfds);
FD_SET(STDIN, &master);
string buffer = "";
while(buffer != "quit"){
readfds = master;
memcpy(&tv1, &tv, sizeof(tv));
if(select(STDIN+1, &readfds, NULL, NULL, &tv1) == -1) perror("select");
if (FD_ISSET(STDIN, &readfds)){
getline(cin, buffer);
cout << "You entered: " << buffer << endl;
}else
cout << "Timed out.\n" << endl;
}
return 0;
}
If you ever read the source of select.c in linux kernel, you'll find that in the select() call, the last parameter timeout will be set to zero after it is used.
So, you should set the value of tv inside the loop, before each call of select().
If memory serves, the call to select() can change the value of tv to indicate the time remaining. You should reinitialize tv before each call to select().
You must put
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
into your loop. Assigning: readfds = master; will not always work (actually I'm pretty sure it will not work in every platform - depending on the definition of fd_et).
also setting tv in a loop is a good idea.
Related
I have a program that I want to exit when I can not open a pipe for read, after N (lets say 30) seconds.
My code works with blocking name pipes and I can not change this.
I know about select() and poll() but I can not get them to work without turning my pipes into non-blocking.
This is my code so far:
struct pollfd fds[1];
int pol_ret;
fds[0].fd = open(pipe_name, O_RDONLY /* | O_NONBLOCK */);
if (fds[0].fd < 0)
{
// send_signal_to_parent();
std::cout << "error while opening the pipe for read, exiting!" << '\n';
return -1;
}
fds[0].events = POLLIN;
int timeout_msecs = 30000; // (30 seconds)
pol_ret = poll(fds, 1, timeout_msecs);
std::cout << "poll returned: "<< pol_ret << '\n';
if (pol_ret == 0)
{
std::cout << "im leaving" << '\n';
return -1;
}
How can I wait only for 30 seconds for a pipe to open for read?
I'm running Linux, debian in particular.
Setup up a timer with a signal handler and wait call open on the fifo.
If the open fails with errno=EINTR and your handler ran, the open call was interrupted by your timer, i.e., it timed out.
Example code:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
volatile sig_atomic_t abort_eh;
void handler(int Sig)
{
abort_eh = 1;
}
int main()
{
struct sigaction sa;
sa.sa_flags = 0;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM,&sa,0);
//try to ensure the fifo exists
(void)mkfifo("fifo",0600);
//open with a timeout of 1s
alarm(1);
int fd;
do{
if (0>(fd=open("fifo",O_RDONLY)))
if(errno==EINTR){
if(abort_eh) return puts("timed out"),1;
else continue; //another signal interrupted it, so retry
}else return perror("open"),1;
}while(0);
alarm(0); //cancel timer
printf("sucessfully opened at fd=%d\n", fd);
}
setitimer or timer_create/timer_settime provide better more fine grained timers than alarm. They also have the possibility of setting the timer to repeat which allows you to resignal in case the first signal "missed" (i.e., ran just before the open call was entered and so failed to break the potentially indefinitely blocking syscall).
I have a C++ function here:
void printTextSlowly(string &s, int speed)
{
int position = 0;
for(char c: s)
{
position++;
std::this_thread::sleep_for(std::chrono::milliseconds(speed));
std::cout << c << std::flush;
// Should run until user presses enter.
//if(cin.ignore())
//{
// std::string subString = s.substr(position);
// std::cout << subString << std::endl;
// break;
//}
}
}
So basically this will slow the text down which it does but when user presses enter, it should stop and print out the rest of the text. With cin.ignore() it waits for the user to do something. I don't want it to wait.
Help is greatly appreciated.
Edit: select is obsolete. Use pool instead
What you want is to wait for a specific amount of time or until you have something on stdin.
Since you are on linux this can be achieved with select.
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
select() and pselect() allow a program to monitor multiple file
descriptors, waiting until one or more of the file descriptors become
"ready" for some class of I/O operation
You don't need multiple file selectors. Just stdin. And set the timeout to 1 millisecond.
Since I don't have a linux handy here is some untested code adapted from the linked page example and your example:
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin to see when it has input. */
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
/* Wait 1 millisecond. */
tv.tv_sec = 0;
tv.tv_usec = 1000;
int position = 0;
for (int position = 0; position < s.length(); ++position)
{
retval = select(1, &rfds, nullptr, nullptr, &tv);
if (retval == -1)
{
perror("select()");
// exit or throw or deal with error
}
else if (retval)
{
// Data available on cin (user pressed enter)
std::string subString = s.substr(position);
std::cout << subString << std::endl;
break;
}
else
{
// No data on cin, continue printing
std::cout << s[position] << std::flush;
}
}
1) Copy the String in a new variable(until it got printed).
2) Use a do-while loop until user presses enter.
3) Find out the remaining string and print after ending the do-while loop.
Hope it helps :)
I am trying to write a simple program to send single characters to a program via a COM port and read the answers I get back. I think I have working script where I can at least send commands via the com port, but when the ReadFile function begins it freezes. I have the comm timeout set for 100ms, so I don't think that it is locking the port, but I may be wrong. I am not getting any errors, and no warnings when I compile. I am very new to C++ (normally work with python), so please be as clear a possible with your answers.
// comtest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <windows.h>
int main(int argc, char **argv)
{
std::cout << "TOP! \n";
char buffer[1];
HANDLE file;
COMMTIMEOUTS timeouts;
DWORD read, written;
DCB port;
char init[] = ""; // e.g., "ATZ" to completely reset a modem.
// open the comm port.
file = CreateFile(L"COM1",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
std::cout << "file made \n";
// get the current DCB, and adjust a few bits to our liking.
memset(&port, 0, sizeof(port));
port.DCBlength = sizeof(port);
// set short timeouts on the comm port.
timeouts.ReadIntervalTimeout = 100;
timeouts.ReadTotalTimeoutMultiplier = 1;
timeouts.ReadTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 100;
int N = 10;
while (N > 1)
{
std::cout << "i'm in the loop!" << N << " loops left \n";
char command [1];
char * commandbuff;
std::cin >> command;
commandbuff = &command[1];
WriteFile(file, commandbuff, sizeof(commandbuff),&written, NULL);
Sleep(1000);
std::cout << "I just slept \n";
ReadFile(file, buffer, sizeof(buffer), &read, NULL);
N--;
}
// close up and go home.
CloseHandle(file);
return 0;
Your code doesn't appear to actually call SetCommTimeouts, so the timeouts you have defined would have no way to be applied.
Receiving data from a com port, don't start reading unless you have first sent a command or something that gets a response. Then, it's preferable to just read one byte at a time, but if you are sending modbus/at commands like I'm doing and know you're expecting 8 bytes back, then it's ok to use readfile to read 8 bytes. Most of the C++ com port examples have SetCommState, SetCommTimeouts, SetCommMask and WaitCommEvent before you can read that single byte.
Mine had an "&" on the second parameter of ReadFile. MS Visual C++ though.
Status = ReadFile(fileusb, &ReadData, sizeof(ReadData), &NoBytesRead, NULL);
I wrote the program
#include<iostream>
using namespace std;
int n;
int main(int argc, char *argv[])
{
std::cout << "Before reading from cin" << std::endl;
// Below reading from cin should be executed within stipulated time
bool b=std::cin >> n;
if (b)
std::cout << "input is integer for n and it's correct" << std::endl;
else
std::cout << "Either n is not integer or no input for n" << std::endl;
return 0;
}
Here std::cin statement would wait for the console for input and will go for sleep mode until we provide some input and press Enter.
I want std::cin statement to go for timeout after 10 seconds(if user doesn't enter any data between 10 seconds then compiler would start executing the next statement of the program present below std::cin statement.
I am able to solve it using multithreading mechanism. Below is my code:
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<iostream>
using namespace std;
void *thread_function(void *arg);
int input_value;
int main(int argc, char *argv[])
{
int res;
pthread_t a_thread;
void *thread_result;
res=pthread_create(&a_thread,NULL,thread_function,NULL);
if(res!=0){
perror("Thread creation error");
exit(EXIT_FAILURE);
}
//sleep(10);
cout<<"cancelling thread"<<endl;
res=pthread_cancel(a_thread);
cout<<"input value="<<input_value<<endl;
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
int res;
res=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
if(res!=0){
perror("Unable to set pthread to cancel enbable state");
exit(EXIT_FAILURE);
}
cin>>input_value;
pthread_exit(&input_value);
}
But here I am facing a problem. Due to the sleep function either user inputs value or not the sleep function by default sleeps for 10 seconds. This is where I am lagging.
How do I solve this problem like using(signals,binary semaphores etc..). Please relate your answer w.r.t my solution(i.e multithreading).
Any information is most welcome...
Since you're on a POSIX machine, you can use e.g. select to check if there's anything on the standard input:
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds)
timeval timeout;
timeout.tv_sec = 5; // A five-second timeout
timeout.tv_usec = 0;
int rc = select(STDIN_FILENO + 1, &fds, nullptr, nullptr, &timeout);
if (rc < 0)
perror("select");
else if (rc == 0)
{
// Timeout
}
else
{
// There is input to be read on standard input
}
Using poll (as suggested by Basile Starynkevitch) it could be done something like this:
struct pollfd poller;
poller.fd = STDIN_FILENO;
poller.events = POLLIN;
poller.revents = 0;
int rc = poll(&poller, 1, 5); // Poll one descriptor with a five second timeout
if (rc < 0)
perror("select");
else if (rc == 0)
{
// Timeout
}
else
{
// There is input to be read on standard input
}
I've tried a few solutions to get this to work and my current solution is pretty hacky, however, it works for my where the other solutions here using select and poll have failed.
My code would sometimes give me a positive result for data being available but then block forever on std::cin.get(); or std::getline(std::cin, STRINGVARIABLE);
My solution:
// Reset flag, initially true so that if cin blocks it will be reset
bool Reset = true;
// Create a c++11 thread to reset cin after a timeout of 100ms
std::thread ResetThread([&Reset](void){
// This thread will wait 100ms
std::this_thread::sleep_for(std::chrono::milliseconds(100));
// Then if the reset flag is still true it will reset cin by closing and opening it
if (Reset) {
close(STDIN_FILENO);
// TODO: Really the output of this open call should be checked for errors
open("/dev/null", O_RDONLY);
}
});
// Now for the standard reading of cin:
std::string Line;
std::getline(std::cin, Line);.
// If cin was read correctly the getline command will return immediately
// This means that the reset flag will be set to false long before the thread tests it.
Reset = false;
// Finally join with the thread.
ResetThread.join();
This code can be joined with the select or poll methods (it is in my code) to prevent creating a new thread every 100ms.
Obviously the appropriateness of this code will depend on the rest of your project, but it works for me so I thought I'd share.
-- EDIT --
After moving between PCs it seems that this code isn't as robust as I'd hoped. I've now accepted just using a separate blocked thread for input, see my answer here:
After fighting with non-blocking cin for a long time it seems the only robust way of doing it is inside its own thread.
See my answer here for an implementation:
https://stackoverflow.com/a/39499548/1427932
I'm currently programming Tetris in C++. Right now I am at the stage where I have finished writing the program but I still need to fix a few bugs and optimize performance.
That being said, one of the flaws in my program is that it can only handle one key-press per second. I need it to handle at least three. You can see the flaw demonstrated by this code:
//Most headers only pertain to my main program.
#include <iostream>
#include <termios.h>
#include <pthread.h>
#include <time.h>
#include <cstring>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
//Timer function.
void *Timer(void*) {
time_t time1, time2;
time1 = time(NULL);
while (time2 - time1 < 1) {
time2 = time(NULL);
}
pthread_exit(NULL);
}
int main() {
//Remove canonical buffering.
struct termios t_old, t_new;
tcgetattr(STDIN_FILENO, &t_old);
t_new = t_old;
t_new.c_lflag &= (~ICANON & ~ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &t_new);
const int STDIN = 0;
struct timeval tv, tv1;
fd_set readfds, readfds2, master;
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&master);
FD_SET(STDIN, &readfds);
FD_SET(STDIN, &master);
char buffer[1];
while(buffer[0] != 'q') {
pthread_t inputTimer;
pthread_create(&inputTimer, NULL, Timer, NULL);
readfds = master;
memcpy(&tv1, &tv, sizeof(tv));
if (select(STDIN+1, &readfds, NULL, NULL, &tv1) == -1) {
perror("select");
}
if (FD_ISSET(STDIN, &readfds)) {
buffer[0] = cin.get();
cout << "You entered: " << buffer << endl;
}
pthread_join(inputTimer, NULL);
cout << "Timed out.\n" << endl;
}
cout << "Game Over." << endl;
return 0;
}
As you can see, the program operates by setting up a one second interval timer and timeval. Because both timers use ints to determine how much time has passed, they cannot be more precise than one second. How can I modify my program to be more precise?
My thought was to copy the value of tv1 to a third value if a key was pressed and then wait for input again but for whatever value time that tv1 was. For example if I press a key when there is only half a second left, the value 0.5 would be taken from tv1 and copied to another variable. Then the program would only wait for half a second for input, instead of the full second. This didn't work, however, because tv1 only ever equals 1 or 0.
Try to use struct timeval and gettimeofday() in sys/time.h. You can achieve microseconds resolution.
Manpage: http://linux.die.net/man/3/gettimeofday
Further info: http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
EDIT:
In Linux (not portable to MinGW under Windows) you could also use poll() (see here), which lets you wait for milliseconds. That would be more efficient because poll suspends the thread execution until time is out.
//Timer function.
void *Timer(void*) {
poll(0, 0, 100); //Suspend thread for 100 ms.
pthread_exit(NULL);
}
The pollfunction is declared in poll.h
The problem here is that pthread_join suspends the main thread until the timer thread completes. You will therefore miss any user input that comes during or after the join. Since you are already using select, you might as well make use of the timeout built into the select statement. If you keep a watch of time elapsed, you can achieve the same effect without the timer thread.