diff options
author | Frédéric Brière <fbriere@fbriere.net> | 2019-06-28 23:38:58 -0400 |
---|---|---|
committer | Frédéric Brière <fbriere@fbriere.net> | 2019-06-29 19:48:20 -0400 |
commit | b3cca3938332011ef9b2454ba5a30f15863930ba (patch) | |
tree | 26228c0f42ea3706cd89eb720ab09b9fed4cfc23 | |
parent | 05082ae12051821b1d969e6672d9e4e5afe1bc07 (diff) | |
download | twinkle-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.cpp | 44 |
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()); |