diff --git a/src/reader.cpp b/src/reader.cpp index 5edf3c30e..88a481ce7 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -3932,6 +3932,11 @@ maybe_t reader_data_t::readline(int nchars_or_0) { } } + // If we ran `exit` anywhere, exit. + exit_loop_requested |= parser().libdata().exit_current_script; + parser().libdata().exit_current_script = false; + if (exit_loop_requested) continue; + if (!event_needing_handling || event_needing_handling->is_check_exit()) { continue; } else if (event_needing_handling->is_eof()) { diff --git a/tests/pexpects/bind.py b/tests/pexpects/bind.py index 68e16d8b6..c1bcebe09 100644 --- a/tests/pexpects/bind.py +++ b/tests/pexpects/bind.py @@ -317,3 +317,19 @@ sendline('bind \cz "echo bound ctrl-z"') expect_prompt() send("\x1A") expect_str("bound ctrl-z") + +# Check that the builtin version of `exit` works +# (for obvious reasons this MUST BE LAST) +sendline('function myexit; echo exit; exit; end; bind \cz myexit') +expect_prompt() +send("\x1A") +expect_str("exit") + +for t in range(0, 5): + if not sp.spawn.isalive(): + break + # This is cheesy, but on CI with thread-sanitizer this can be slow enough that the process is still running, so we sleep for a bit. + time.sleep(1) +else: + print("Fish did not exit via binding!") + sys.exit(1)