From 75c23fb66297c7fcd3eba0d485a7bb4f0116ad47 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 3 Jun 2025 07:00:45 -0700 Subject: listener: deodorize EOF handling. This is motivated by seeing a poor behavior, whose manifestation is platform dependent. In the listener if we run, say (get-json) and hit Ctrl-D, then after the get-json function reports failure, the listener will quit as if it received EOF. On older glibc/Linux systems, the listener does not experience EOF. Furthermore, in the EOF situation, this misleading diagnostic is seen: ** error reading interactive input. * parser.c (repl): Call clear_error on in_stream just before calling linenoise. This gets rid of any sticky EOF condition left behind by an input operation. On POSIX systems, if you use stdin to read from a terminal and receive EOF, you must clearerr(stdin) before continuing to read from the terminal. Otherwise input operations on the stream can just return the cached error indication without attempting to perform any input on the file descriptor. Somehow we are getting away without doing this on older systems like Ubuntu 18. Maybe something changed in the glibc stdio implementation. * linenoise/linenoise.c (complete_line): Don't directly return -1 on EOF, just set the stop = 1 variable, so the WEOF value will be returned, similarly to how it is done in history_search. (history_search): Set the error variable on EOF. (edit): Set the error variable on EOF. --- linenoise/linenoise.c | 8 ++++---- parser.c | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c index b905d444..15d919b8 100644 --- a/linenoise/linenoise.c +++ b/linenoise/linenoise.c @@ -635,10 +635,8 @@ static int complete_line(lino_t *ls, int substring) { free_completions(&lc); lino_os.free_fn(lt); ls->error = (lino_os.eof_fn(ls->tty_ifs) ? lino_eof : lino_ioerr); - return -1; - } - - switch (c) { + stop = 1; + } else switch (c) { case TAB: i = (i+1) % (lc.len+1); if (i == lc.len) generate_beep(ls); @@ -751,6 +749,7 @@ static int history_search(lino_t *l) handle_resize(lc, l); continue; } + lc->error = (lino_os.eof_fn(lc->tty_ifs) ? lino_eof : lino_ioerr); stop = 1; } else { if (vb) @@ -2120,6 +2119,7 @@ static int edit(lino_t *l, const wchar_t *prompt) if (c == WEOF) { ret = l->len ? l->len : -1; + l->error = (lino_os.eof_fn(l->tty_ifs) ? lino_eof : lino_ioerr); goto out; } diff --git a/parser.c b/parser.c index df37232f..0237d12f 100644 --- a/parser.c +++ b/parser.c @@ -1769,6 +1769,8 @@ val repl(val bindings, val in_stream, val out_stream, val env) uw_push_handler(&uw_handler, cons(warning_s, nil), rw_f); + clear_error(in_stream); + line_w = linenoise(ls, c_str(prompt, self)); uw_pop_frame(&uw_handler); -- cgit v1.2.3