fix Ctrl-C swallowing the next line
readline only redraws the prompt on Ctrl-C: the half-typed text stays in its buffer and the interrupt flag outlives the prompt, so the line typed next was silently discarded. Register a signal event hook that empties the line, the way bash does, and clear the flag around readline instead of eating the line: a Ctrl-C during a command still aborts the turn, and one during a multi-line task still abandons it. Two pty-based regression tests cover the idle-prompt and mid-line cases.
This commit is contained in:
@@ -42,6 +42,16 @@ static int GN(json_object *o, const char *k, int d) { json_object *v = G(o, k);
|
||||
|
||||
static volatile sig_atomic_t IN;
|
||||
static void onint(int s) { (void)s; IN = 1; }
|
||||
/* readline calls this from its input loop, in a safe context, after it has
|
||||
dealt with a signal caught while it was reading a line. A Ctrl-C only
|
||||
redraws the prompt: the half-typed text stays in the buffer, so clear it
|
||||
here, the way bash does. The flag is left set on purpose; the prompt loop
|
||||
clears it, so a Ctrl-C during a command still aborts the turn, and one
|
||||
during a multi-line task still abandons it. */
|
||||
static int ci_hook(void) {
|
||||
if(IN) { rl_replace_line("", 1); rl_redisplay(); }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *EP, *KEY, *MOD, *RSN, *SF, *TMP, *SYS, *SELF, SH[256] = "/bin/sh";
|
||||
static int TO = 120, QUIT, CLR = 1;
|
||||
@@ -402,6 +412,7 @@ int main(int argc, char **argv) {
|
||||
if(!(e = getenv("SHELL")) || access(e, X_OK)) e = access("/bin/bash", X_OK) ? "/bin/sh" : "/bin/bash";
|
||||
snprintf(SH, sizeof SH, "%s", e);
|
||||
signal(SIGINT, onint); signal(SIGPIPE, SIG_IGN);
|
||||
rl_signal_event_hook = ci_hook;
|
||||
create(); load();
|
||||
if((e = getenv("SOLO_MODEL")) && *e) { setstr(&MOD, e); A(SSN, "model", S(e)); }
|
||||
if((e = getenv("SOLO_TEMP")) && *e) { TEMP = atof(e); A(SSN, "temperature", D(TEMP)); }
|
||||
@@ -416,8 +427,9 @@ int main(int argc, char **argv) {
|
||||
free(task);
|
||||
while(!QUIT) {
|
||||
snprintf(pb, sizeof pb, "\001%s\002> \001%s\002", CLR ? BLD : "", CLR ? OF : "");
|
||||
IN = 0; /* a Ctrl-C during a command must not reach the line about to be typed */
|
||||
if(!(ln = readline(pb))) { puts(""); break; }
|
||||
if(IN) { IN = 0; free(ln); continue; }
|
||||
IN = 0; /* a Ctrl-C during the line only cleared that line, not this turn */
|
||||
ac = ln;
|
||||
for(;;) {
|
||||
size_t l = strlen(ac);
|
||||
|
||||
Reference in New Issue
Block a user