summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-06-03 07:00:45 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-06-03 07:00:45 -0700
commit75c23fb66297c7fcd3eba0d485a7bb4f0116ad47 (patch)
tree2b5315d11091764c382b9a28cf03e6c08a8f6ecf
parent28256ba13885ac924d90dd0b0e639165af7ec373 (diff)
downloadtxr-75c23fb66297c7fcd3eba0d485a7bb4f0116ad47.tar.gz
txr-75c23fb66297c7fcd3eba0d485a7bb4f0116ad47.tar.bz2
txr-75c23fb66297c7fcd3eba0d485a7bb4f0116ad47.zip
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.
-rw-r--r--linenoise/linenoise.c8
-rw-r--r--parser.c2
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);