summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrédéric Brière <fbriere@fbriere.net>2019-06-28 23:38:58 -0400
committerFrédéric Brière <fbriere@fbriere.net>2019-06-29 19:48:20 -0400
commitb3cca3938332011ef9b2454ba5a30f15863930ba (patch)
tree26228c0f42ea3706cd89eb720ab09b9fed4cfc23
parent05082ae12051821b1d969e6672d9e4e5afe1bc07 (diff)
downloadtwinkle-b3cca3938332011ef9b2454ba5a30f15863930ba.tar
twinkle-b3cca3938332011ef9b2454ba5a30f15863930ba.tar.gz
twinkle-b3cca3938332011ef9b2454ba5a30f15863930ba.tar.lz
twinkle-b3cca3938332011ef9b2454ba5a30f15863930ba.tar.xz
twinkle-b3cca3938332011ef9b2454ba5a30f15863930ba.zip
Make Readline non-blocking: Use Readline's callback interface
When Twinkle is running in CLI mode and is sent a "quit" command to its local socket, it will currently not respond immediately, but rather wait until the next line has been read from its standard input (issue #143). This is due to the blocking nature of readline(), which only returns once a complete line has been read. Switching to Readline's "alternate" callback interface is the first step in addressing this issue. (As a bonus, this also fixes a bug where the line pointer returned by readline() was not freed correctly.)
-rw-r--r--src/userintf.cpp44
1 files changed, 25 insertions, 19 deletions
diff --git a/src/userintf.cpp b/src/userintf.cpp
index f75a140..772184d 100644
--- a/src/userintf.cpp
+++ b/src/userintf.cpp
@@ -86,22 +86,29 @@ char * tw_command_generator (const char *text, int state)
return ((char *)NULL);
}
-char *tw_readline(const char *prompt)
+// Ugly hack to allow invoking methods on our object from within a C-style
+// callback function. This relies on the object being a singleton.
+static t_userintf *cb_user_intf;
+// Callback method (a.k.a. "line handler") that will be invoked by Readline
+// once a complete line has been read.
+static void tw_readline_cb(char *line)
{
- static char *line = NULL;
-
if (!line) {
+ // EOF
+ cout << endl;
+ // Calling this from the line handler prevents one extra
+ // prompt from being displayed. (The duplicate call later on
+ // will not be an issue.)
+ rl_callback_handler_remove();
+
+ cb_user_intf->cmd_quit();
+ } else {
+ if (*line) {
+ add_history(line);
+ cb_user_intf->exec_command(line);
+ }
free(line);
- line = NULL;
- }
-
- line = readline(prompt);
-
- if (line && *line) {
- add_history(line);
}
-
- return line;
}
/////////////////////////////
@@ -2206,16 +2213,15 @@ void t_userintf::run(void) {
read_history(sys_config->get_history_file().c_str());
stifle_history(CLI_MAX_HISTORY_LENGTH);
+ // Additional stuff for using the Readline callback interface
+ cb_user_intf = this;
+ rl_callback_handler_install(CLI_PROMPT, tw_readline_cb);
while (!end_interface) {
- char *command_line = tw_readline(CLI_PROMPT);
- if (!command_line){
- cout << endl;
- break;
- }
-
- exec_command(command_line);
+ rl_callback_read_char();
}
+
+ rl_callback_handler_remove();
// Terminate phone functions
write_history(sys_config->get_history_file().c_str());