I have a multi-threaded Windows console app whose control thread runs a user input loop like this:
char c;
do {
cin >> c;
// Alter activity based on c
} while(c != 'q')
// Tell other threads to close, .join(), and do cleanup
However at a certain time I want the program itself to be able to gracefully quit. The most obvious way to do so would be to put a "q\n" onto the stdin stream. Is there a reasonable way to do that?
Or a good alternative for a callback to force exit the main control loop (on the primary thread) so that the program falls through to the subsequent cleanup methods?
(The closest I have found so far is this which requires spawning a child process and seems like kludgy overkill at best.)
You can use another flag as loop break condition for all of your threads. The problem with interthread-communication can be solved by synchronization objects which came with C++11 like atomics or mutex.
I ended up using the suggestion from #Captain Obvlious, but even that was tricky (thanks Windows!): As soon as a control signal is handled it causes all sorts of problems with the unchecked char input loop. However, with the following additions any thread can gracefully end the program by calling GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
bool exiting = false;
bool cleanedUp = false;
void Cleanup() {
if(!cleanedUp) cleanedUp = true;
else return;
// Tell other threads to close, .join(), and do cleanup
}
// https://msdn.microsoft.com/en-us/library/ms683242(v=vs.85).aspx
bool ConsoleControl(DWORD dwCtrlType) {
exiting = true; // This will cause the stdin loop to break
Cleanup();
return false;
}
int main() {
SetConsoleCtrlHandler((PHANDLER_ROUTINE) ConsoleControl, true);
.
.
.
// Main user control loop
char c;
do {
cin >> c;
if(exiting) break;
if(c < 0) continue; // This must be a control character
// Alter activity based on c
} while(c != 'q')
Cleanup();
return 0;
}
This is an old question but I stumbled upon it and ended up solving the original problem.
I used the WriteConsoleInput function to simulate a user entering keystrokes to the console. This code sample is based off of This question.
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD dwTmp;
INPUT_RECORD ir[2];
ir[0].EventType = KEY_EVENT;
ir[0].Event.KeyEvent.bKeyDown = TRUE;
ir[0].Event.KeyEvent.dwControlKeyState = 0;
ir[0].Event.KeyEvent.uChar.UnicodeChar = 'q';
ir[0].Event.KeyEvent.wRepeatCount = 1;
ir[0].Event.KeyEvent.wVirtualKeyCode = 'Q';
ir[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey('Q', MAPVK_VK_TO_VSC);
ir[1].EventType = KEY_EVENT;
ir[1].Event.KeyEvent.bKeyDown = TRUE;
ir[1].Event.KeyEvent.dwControlKeyState = 0;
ir[1].Event.KeyEvent.uChar.UnicodeChar = VK_RETURN;
ir[1].Event.KeyEvent.wRepeatCount = 1;
ir[1].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
ir[1].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
WriteConsoleInput(hStdin, ir, 2, &dwTmp);
On my system MAPVK_VK_TO_VSC wasn't defined so I used 0 instead.
You should add error checking where appropriate.
I hope this helps.
Related
I'm trying to set up some test software for code that is already written (that I cannot change). The issue I'm having is that it is getting hung up on certain calls, so I want to try to implement something that will kill the process if it does not complete in x seconds.
The two methods I've tried to solve this problem were to use fork or pthread, both haven't worked for me so far though. I'm not sure why pthread didn't work, I'm assuming it's because the static call I used to set up the thread had some issues with the memory needed to run the function I was calling (I continually got a segfault while the function I was testing was running). Fork worked initially, but on the second time I would fork a process, it wouldn't be able to check to see if the child had finished or not.
In terms of semi-pseudo code, this is what I've written
test_runner()
{
bool result;
testClass* myTestClass = new testClass();
pid_t pID = fork();
if(pID == 0) //Child
{
myTestClass->test_function(); //function in question being tested
}
else if(pID > 0) //Parent
{
int status;
sleep(5);
if(waitpid(0,&status,WNOHANG) == 0)
{
kill(pID,SIGKILL); //If child hasn't finished, kill process and fail test
result = false;
}
else
result = true;
}
}
This method worked for the initial test, but then when I would go to test a second function, the if(waitpid(0,&status,WNOHANG) == 0) would return that the child had finished, even when it had not.
The pthread method looked along these lines
bool result;
test_runner()
{
long thread = 1;
pthread_t* thread_handle = (pthread_t*) malloc (sizeof(pthread_t));
pthread_create(&thread_handle[thread], NULL, &funcTest, (void *)&thread); //Begin class that tests function in question
sleep(10);
if(pthread_cancel(thread_handle[thread] == 0))
//Child process got stuck, deal with accordingly
else
//Child process did not get stuck, deal with accordingly
}
static void* funcTest(void*)
{
result = false;
testClass* myTestClass = new testClass();
result = myTestClass->test_function();
}
Obviously there is a little more going on than what I've shown, I just wanted to put the general idea down. I guess what I'm looking for is if there is a better way to go about handling a problem like this, or maybe if someone sees any blatant issues with what I'm trying to do (I'm relatively new to C++). Like I mentioned, I'm not allowed to go into the code that I'm setting up the test software for, which prevents me from putting signal handlers in the function I'm testing. I can only call the function, and then deal with it from there.
If c++11 is legit you could utilize future with wait_for for this purpose.
For example (live demo):
std::future<int> future = std::async(std::launch::async, [](){
std::this_thread::sleep_for(std::chrono::seconds(3));
return 8;
});
std::future_status status = future.wait_for(std::chrono::seconds(5));
if (status == std::future_status::timeout) {
std::cout << "Timeout" <<endl ;
} else{
cout << "Success" <<endl ;
} // will print Success
std::future<int> future2 = std::async(std::launch::async, [](){
std::this_thread::sleep_for(std::chrono::seconds(3));
return 8;
});
std::future_status status2 = future2.wait_for(std::chrono::seconds(1));
if (status2 == std::future_status::timeout) {
std::cout << "Timeout" <<endl ;
} else{
cout << "Success" <<endl ;
} // will print Timeout
Another thing:
As per the documentation using waitpid with 0 :
meaning wait for any child process whose process group ID is equal to
that of the calling process.
Avoid using pthread_cancel it's probably not a good idea.
I am a newbie in c++ working on what should be a pretty basic file read and then process data functionality and I keep getting stuck on being able to at least provide a "state" of on thread to another so that data could be consumed. This just maybe something really basic that I am overlooking - could use some insight into using pthreads in c++.
Bellow is some basic extracted code that functions OK, reads the file and provides data to be processed. Another thread that will process the data needs to know the state of this one.
What would be the best strategy? I am attempting to request the state of the thread through a function from another thread but receive incorrect response.
Reader::Reader(){
_threadId = 1;
_msg = NONE; // enum NONE, READ, STOP
active = false;
pthread_mutex_init(&_mutex, 0);
}
Reader::~Reader(){
pthread_mutex_destroy(&_mutex);
}
void Reader::read(){
_msg = READ;
active = true;
pthread_create(&_threadId, 0, work, this);
}
void * Reader::work(void *myselfreader){
Reader * reader = (Reader*)myselfreader;
reader->loop();
pthread_exit(0);
return 0;
}
void Reader::loop(){
while(active){
pthread_mutex_lock(&_mutex);
switch(_msg){
case READ:
// do the reading of the IO file - which works fine
// once done reading the file - the _msg is set to STOP
break;
case STOP:
stopThread();
break;
default:
break;
}
pthread_mutex_unlock(&_mutex);
}
return;
}
void Reader::stopThread(){
active = false;
_msg = ENC_NONE;
pthread_join(_threadId, 0);
}
/*****************/
int Reader::getReaderState(){
// another thread needs to know the state of this thread
//
return _msg // ??
return active // ??
}
It seems that you have race condition somewhere in your code.
You need to protect your _msg variable with mutex. Every time you need to update _msg variable request mutex, update variable and close the mutex. You need to do the same thing for the reading in getReaderState() function - acquire mutex, copy variable into temp, release mutex and return temp variable.
For easy and error-prone usage, you should create getter and setter function for accessing _msg field which will be guarded by the same mutex (and not the one that you are already using):
void setMsg(int msg)
{
pthread_mutex_lock(&msg_mutex);
_msg = msg;
pthread_mutex_unlock(&msg_mutex);
}
int getMsg()
{
int tmp;
pthread_mutex_lock(&msg_mutex);
tmp = _msg;
pthread_mutex_unlock(&msg_mutex);
return tmp;
}
I got this following function with me working now. But what I need to improve is that it would read input from the keyboard (on the terminal) EVEN THOUGH IT IS NOT BEING PRESSED. I need to know when it is NOT pressed (idle) so that the switch case block will fall into the default section. At this point, the read() function waits until there's an input from the user. Can anyone give a suggestion just based on modifying this following code?
NOTE: I'm a Java programmer, and still learning C/C++ so it might be hard to get in my head a little bit. Thanks guys..
EDIT: I found this link, and seems to have something related to what i'm looking for at the line of fcntl(STDIN_FILENO,F_SETFL,flags | O_NONBLOCK); . But since I barely know anything in C, I completely have no Idea what it's saying, yet.
http://www.codeguru.com/forum/showthread.php?t=367082
int kfd = 0;
struct termios cooked, raw;
char c;
bool dirty = false;
//get the console in raw mode
tcgetattr(kfd, &cooked);
memcpy(&raw, &cooked, sizeof(struct termios));
raw.c_lflag &=~ (ICANON | ECHO);
// Setting a new line, then end of file
raw.c_cc[VEOL] = 1;
raw.c_cc[VEOF] = 2;
tcsetattr(kfd, TCSANOW, &raw);
puts("Reading from keyboard");
puts("=====================");
puts("Use arrow keys to navigate");
while(true){
//get the next event from the keyboard
if(read(kfd, &c, 1) < 0)
{
perror("read():");
exit(-1);
}
linear_ = angular_ = 0;
ROS_DEBUG("value: 0x%02X\n", c);
switch(c)
{
case KEYCODE_L:
ROS_DEBUG("LEFT");
angular_ = -1.0;
dirty = true;
break;
case KEYCODE_R:
ROS_DEBUG("RIGHT");
angular_ = 1.0;
dirty = true;
break;
case KEYCODE_U:
ROS_DEBUG("UP");
linear_ = 1.0;
dirty = true;
break;
case KEYCODE_D:
ROS_DEBUG("DOWN");
linear_ = -1.0;
dirty = true;
break;
default:
ROS_DEBUG("RELEASE");
linear_ = 0;
angular_ = 0;
dirty = true;
break;
}
The OP seems to have answered their question:
I think I solved my problem. Please, anyone, verify and let me know if this is the right way to do it, or is it the complete way to do it (am I missing any other addition step e.g. resetting it back again -if that even makes sense) .
So what i found is to add this 3 lines before entering the while loop:
flags = fcntl(0, F_GETFL, 0); /* get current file status flags */
flags |= O_NONBLOCK; /* turn off blocking flag */
fcntl(0, F_SETFL, flags); /* set up non-blocking read */
I have roughly created the following code to call a child process:
// pipe meanings
const int READ = 0;
const int WRITE = 1;
int fd[2];
// Create pipes
if (pipe(fd))
{
throw ...
}
p_pid = fork();
if (p_pid == 0) // in the child
{
close(fd[READ]);
if (dup2(fd[WRITE], fileno(stdout)) == -1)
{
throw ...
}
close(fd[WRITE]);
// Call exec
execv(argv[0], const_cast<char*const*>(&argv[0]));
_exit(-1);
}
else if (p_pid < 0) // fork has failed
{
throw
}
else // in th parent
{
close(fd[WRITE]);
p_stdout = new std::ifstream(fd[READ]));
}
Now, if the subprocess does not write too much to stdout, I can wait for it to finish and then read the stdout from p_stdout. If it writes too much, the write blocks and the parent waits for it forever.
To fix this, I tried to wait with WNOHANG in the parent, if it is not finished, read all available output from p_stdout using readsome, sleep a bit and try again. Unfortunately, readsome never reads anything:
while (true)
{
if (waitid(P_PID, p_pid, &info, WEXITED | WNOHANG) != 0)
throw ...;
else if (info.si_pid != 0) // waiting has succeeded
break;
char tmp[1024];
size_t sizeRead;
sizeRead = p_stdout->readsome(tmp, 1024);
if (sizeRead > 0)
s_stdout.write(tmp, sizeRead);
sleep(1);
}
The question is: Why does this not work and how can I fix it?
edit: If there is only child, simply using read instead of readsome would probably work, but the process has multiple children and needs to react as soon as one of them terminates.
As sarnold suggested, you need to change the order of your calls. Read first, wait last. Even if your method worked, you might miss the last read. i.e. you exit the loop before you read the last set of bytes that was written.
The problem might be is that ifstream is non-blocking. I've never liked iostreams, even in my C++ projects, I always liked the simplicity of C's stdio functions (i.e. FILE*, fprintf, etc). One way to get around this is to read if the descriptor is readable. You can use select to determine if there is data waiting on that pipe. You're going to need select if you are going to read from multiple children anyway, so might as well learn it now.
As for a quick isreadable function, try something like this (please note I haven't tried compiling this):
bool isreadable(int fd, int timeoutSecs)
{
struct timeval tv = { timeoutSecs, 0 };
fd_set readSet;
FD_ZERO(&readSet);
return select(fds, &readSet, NULL, NULL, &tv) == 1;
}
Then in your parent code, do something like:
while (true) {
if (isreadable(fd[READ], 1)) {
// read fd[READ];
if (bytes <= 0)
break;
}
}
wait(pid);
I'd suggest re-writing the code so that it doesn't call waitpid(2) until after read(2) calls on the pipe return 0 to signify end-of-file. Once you get the end-of-file return from your read calls, you know the child is dead, and you can finally waitpid(2) for it.
Another option is to de-couple the reading from the reaping even further and perform the wait calls in a SIGCHLD signal handler asynchronously to the reading operations.
I am writing program in c++ which runs GNU readline in separate thread. When main thread is exited I need to finish the thread in which readline() function is called. The readline() function is returned only when standart input came (enter pressed).
Is there any way to send input to application or explicitly return from readline function?
Thanks in advance.
Instead of returning from main thread, call exit(errno). All other threads will be killed nastily!
Or, if you wanted to be nicer, and depending on your OS, you could send a signal to the readline thread, which would interrupt the syscall.
Or, if you wanted to be cleverer, you could run readline in async mode, using a select() loop with a timeout so that your thread never blocks in readine functions, and your thread can clean up after itself.
I experimented with this situation as well. I thought perhaps one could call close(STDIN_FILENO), which does cause readline to return on the other thread, but for some reason it leaves the terminal in a bad state (doesn't echo characters so you can't see what you're typing). However, a call to the 'reset' command will fix this, so the full alternative is:
close(STDIN_FILENO);
pthread_join(...); // or whatever to wait for thread exit
system("reset -Q"); // -Q to avoid displaying cruft
However, the final better solution I used, inspired by the other suggestions, was to override rl_getc:
rl_getc_function = getc; // stdio's getc passes
and then you can use pthread_kill() to send a signal to interrupt the getc, which returns a -1 to readline, which returns a NULL to the calling thread so you can exit cleanly instead of looping for the next input (the same as would happen if the user EOF'd by ctrl-D)
Now you can have your cake (easy blocking readlines) and eat it too (be able to stop by external event without screwing up the terminal)
C++ standard input is not designed to be thread safe. So, even if there was a method to programatically stop it from waiting input, you wouldn't be able to call it from another thread. Of course, there could be an implementation specific way to do so.
Old thread but still readline API seems not explored.
In order to interrupt readline first I disabled readline signal handlers.
Do not look at the ugly global_buffer I'm using - it's just an example
http://www.delorie.com/gnu/docs/readline/rlman_43.html
Reader Thread:
pthread_mutex_t lock;
int isBufferReady = 0;
char global_buffer[2500]; /// Assuming that reads will not be any bigger
void *reader_thread(void *arg)
{
rl_getc_function = getc;
rl_catch_signals = 0;
rl_catch_sigwinch = 0;
char *input;
while ( (input = readline( NULL )) )
{
i = strlen(input)-1;
if ( input[i] == '\0' )
return NULL;
/// Due to TAB there might be a whitespace in the end
while ( i > 0 )
{
if ( isspace(input[i]) )
{
input[i] = '\0';
}
else
{
break;
}
i--;
}
pthread_mutex_lock(&lock);
read_file_function( input, buffer );
free(input);
isBufferReady = 1;
pthread_mutex_unlock(&lock);
}
printf( "Im closed \n" );
return NULL;
}
Signal handler:
volatile int keepRunning = 1;
void SIG_handler(int signal)
{
int static sig_count = 0;
switch ( signal )
{
case SIGUSR2:
{
/// Yeah I know I should not printf in a signal handler
printf( "USR2: %d \n", sig_count++);
break;
}
default:
{
printf( " SIGHANDLE\n" );
keepRunning = 0;
break;
}
}
}
main:
int main( int argc, char *argv[] )
{
pthread_t file_reader;
{ /// Signal Handler registration
struct sigaction sigact = {{0}};
sigact.sa_handler = SIG_handler;
// sigact.sa_flags = SA_RESTART;
sigaction(SIGINT , &sigact, NULL);
sigaction(SIGQUIT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGHUP, &sigact, NULL);
// sigaction(SIGUSR1, &sigact, NULL);
sigaction(SIGUSR2, &sigact, NULL);
}
pthread_create( &file_reader, NULL, reader_thread, NULL );
while(keepRunning)
{
pthread_mutex_lock(&lock);
if( !isBufferReady )
{
... fill in global_buffer according to some algorithm
}
pthread_mutex_unlock(&lock);
usleep(10);
pthread_mutex_lock(&lock);
if(isBufferReady)
isBufferReady = 0;
... some operation on the 'global_buffer' like write its contents to socket
pthread_mutex_unlock(&lock);
usleep(10);
}
signal(SIGINT, SIG_DFL);
pthread_cancel( file_reader );
pthread_join( file_reader, NULL);
pthread_mutex_destroy(&lock);
rl_cleanup_after_signal();
return 0;
}
With this (nowhere near perfect) code snippet I was able to finally interrupt readline without described prevously flakiness.
Used this code snippet for interactive debug purposes where I had prepared packets in simple text files and read-in those files with the help of readline.