tags:

views:

223

answers:

3

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.

+1  A: 

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.

kgiannakakis
+2  A: 

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.

CuriousPanda
Thanks, I have done by this way. I reimplementa readline get_char function, to use non blocking input and use select() function.
Sasun Hambardzumyan
I have the same problem but I use python. Pythons sys.exit() does not call exit(0) but throws the SystemExit exception. Is there another way to stop the command loop from a different thread? Currently I use `os.kill(os.getpid(), signal.SIGINT); sys.exit()` which isn't very nice, but it works.
panzi
A: 

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)

Ethan