From fe0f8fd0404e1dfda65b8c14c70cb26ffde26a70 Mon Sep 17 00:00:00 2001 From: Ilya Verbin <iverbin@tarantool.org> Date: Mon, 28 Aug 2023 21:20:11 +0300 Subject: [PATCH] main: display a message when local console is exited Consider the following example: ``` tarantool -e "box.cfg{} require('console').start()" ``` When a local console is exited by pressing Ctrl+D, Tarantool seemingly freezes - console stops to work, typed characters are not echoed. But the event loop is not stopped because there are background fibers running. This patch adds a message that Ctrl+C should be pressed in such a case. Closes #7017 NO_DOC=minor --- ...gh-7017-display-message-on-console-exit.md | 4 ++ src/box/lua/console.c | 13 +++++++ src/box/lua/console.h | 10 +++++ src/box/lua/console.lua | 1 + src/main.cc | 6 +++ .../gh_7017_message_on_console_exit_test.lua | 37 +++++++++++++++++++ 6 files changed, 71 insertions(+) create mode 100644 changelogs/unreleased/gh-7017-display-message-on-console-exit.md create mode 100644 test/app-luatest/gh_7017_message_on_console_exit_test.lua diff --git a/changelogs/unreleased/gh-7017-display-message-on-console-exit.md b/changelogs/unreleased/gh-7017-display-message-on-console-exit.md new file mode 100644 index 0000000000..5a021f3361 --- /dev/null +++ b/changelogs/unreleased/gh-7017-display-message-on-console-exit.md @@ -0,0 +1,4 @@ +## bugfix/core + +* Now the "Type Ctrl-C to exit Tarantool" message is displayed when a local + console is exited, but background fibers are running (gh-7017). diff --git a/src/box/lua/console.c b/src/box/lua/console.c index efa49e5626..493f414e3c 100644 --- a/src/box/lua/console.c +++ b/src/box/lua/console.c @@ -54,6 +54,8 @@ #include <string.h> #include <strings.h> +bool is_console_exited; + struct rlist on_console_eval = RLIST_HEAD_INITIALIZER(on_console_eval); static struct luaL_serializer *serializer_yaml; @@ -727,6 +729,16 @@ lbox_console_run_on_eval(struct lua_State *L) return 0; } +/** + * Sets `is_console_exited' to true. + */ +static int +lbox_console_console_exited(MAYBE_UNUSED struct lua_State *L) +{ + is_console_exited = true; + return 0; +} + int console_session_fd(struct session *session) { @@ -897,6 +909,7 @@ tarantool_lua_console_init(struct lua_State *L) {"format_yaml", lbox_console_format_yaml}, {"format_lua", lbox_console_format_lua}, {"run_on_eval", lbox_console_run_on_eval}, + {"console_exited", lbox_console_console_exited}, {NULL, NULL} }; luaT_newmodule(L, "console.lib", consolelib); diff --git a/src/box/lua/console.h b/src/box/lua/console.h index 29348f5af3..d0b25272c4 100644 --- a/src/box/lua/console.h +++ b/src/box/lua/console.h @@ -31,12 +31,22 @@ * SUCH DAMAGE. */ +#include <stdbool.h> #include "small/rlist.h" #if defined(__cplusplus) extern "C" { #endif /* defined(__cplusplus) */ +/** + * If a local console is exited and there are active libev events (e.g. there's + * a background fiber running), Tarantool seemingly freezes - console stops to + * work, typed characters are not echoed. This flag is used by main() to display + * a message to stdout to make things clear. + * The flag is false if the local console was never started or still running. + */ +extern bool is_console_exited; + /** * Triggers invoked on console eval. * Passed eval expression string. diff --git a/src/box/lua/console.lua b/src/box/lua/console.lua index 59f4f90dc8..05ea4aaf28 100644 --- a/src/box/lua/console.lua +++ b/src/box/lua/console.lua @@ -869,6 +869,7 @@ local function start() session_internal.create(1, "repl") -- stdin fileno repl(self) started = false + internal.console_exited() end -- diff --git a/src/main.cc b/src/main.cc index 572808c482..933fef626e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -76,6 +76,7 @@ #include "title.h" #include <libutil.h> #include "box/lua/init.h" /* box_lua_init() */ +#include "box/lua/console.h" #include "box/session.h" #include "box/memtx_tx.h" #include "box/module_cache.h" @@ -968,6 +969,11 @@ main(int argc, char **argv) if (say_entering_the_event_loop) say_info("entering the event loop"); systemd_snotify("READY=1"); + if (is_console_exited) { + printf("Exited console. Type Ctrl-C to exit " + "Tarantool.\n"); + fflush(stdout); + } ev_now_update(loop()); ev_run(loop(), 0); } diff --git a/test/app-luatest/gh_7017_message_on_console_exit_test.lua b/test/app-luatest/gh_7017_message_on_console_exit_test.lua new file mode 100644 index 0000000000..0df443fe60 --- /dev/null +++ b/test/app-luatest/gh_7017_message_on_console_exit_test.lua @@ -0,0 +1,37 @@ +local popen = require('popen') +local t = require('luatest') +local g = t.group('gh-7017') + +-- Read from ph:stdout and fail if it doesn't contain a `pattern'. +local function grep_stdout_or_fail(ph, pattern) + local output = '' + t.helpers.retrying({}, function() + local chunk = ph:read({timeout = 0.05}) + if chunk ~= nil then + output = output .. chunk + end + t.assert_str_contains(output, pattern) + end) +end + +-- Check that the message is printed when local console is exited. +g.test_message_on_console_exit = function() + local tarantool_exe = arg[-1] + local lua_code = [[ fiber = require('fiber') + fiber.new(function() fiber.sleep(120) end) + print('gh-7017 started') + require('console').start() ]] + local ph = popen.new({tarantool_exe, '-e', lua_code}, + {stdin = popen.opts.PIPE, stdout = popen.opts.PIPE}) + t.assert(ph) + + -- Wait for the process startup. + grep_stdout_or_fail(ph, "gh-7017 started") + + -- Send EOF to exit console. + ph:shutdown({stdin = true}) + + -- Check that the message is printed. + grep_stdout_or_fail(ph, "Exited console. Type Ctrl-C to exit Tarantool.") + ph:close() +end -- GitLab