diff --git a/changelogs/unreleased/gh-9411-fix-graceful-shutdown-break-on-script-exit.md b/changelogs/unreleased/gh-9411-fix-graceful-shutdown-break-on-script-exit.md new file mode 100644 index 0000000000000000000000000000000000000000..4995050b2dfe7e88cf5e3234859f4184cb2dbc1f --- /dev/null +++ b/changelogs/unreleased/gh-9411-fix-graceful-shutdown-break-on-script-exit.md @@ -0,0 +1,3 @@ +## bugfix/core + +* Fixed graceful shutdown break on init script exit (gh-9411). diff --git a/src/main.cc b/src/main.cc index 49980efa03cba57e51ffce04b02c5e2d8e51010a..018c2ce1e2fafe9cf2ab48b56c704edb12dd5dab 100644 --- a/src/main.cc +++ b/src/main.cc @@ -107,7 +107,8 @@ static double start_time; /** A preallocated fiber to run on_shutdown triggers. */ static struct fiber *on_shutdown_fiber = NULL; /** A flag restricting repeated execution of tarantool_exit(). */ -static bool is_shutting_down = false; +static bool shutdown_started = false; +static bool shutdown_finished = false; static int exit_code = 0; char tarantool_path[PATH_MAX]; @@ -162,7 +163,7 @@ on_shutdown_f(va_list ap) fiber_sleep(0.0); /* Handle spurious wakeups. */ - while (!is_shutting_down) + while (!shutdown_started) fiber_yield(); if (on_shutdown_run_triggers() != 0) { @@ -170,6 +171,7 @@ on_shutdown_f(va_list ap) diag_log(); diag_clear(diag_get()); } + shutdown_finished = true; ev_break(loop(), EVBREAK_ALL); return 0; } @@ -178,7 +180,7 @@ void tarantool_exit(int code) { start_loop = false; - if (is_shutting_down) { + if (shutdown_started) { /* * We are already running on_shutdown triggers, * and will exit as soon as they'll finish. @@ -186,7 +188,7 @@ tarantool_exit(int code) */ return; } - is_shutting_down = true; + shutdown_started = true; exit_code = code; box_broadcast_fmt("box.shutdown", "%b", true); fiber_wakeup(on_shutdown_fiber); @@ -1074,10 +1076,10 @@ main(int argc, char **argv) * init script, and there was neither os.exit nor SIGTERM, then call * tarantool_exit and start an event loop to run on_shutdown triggers. */ - if (!is_shutting_down) { + if (!shutdown_started) tarantool_exit(exit_code); + if (!shutdown_finished) ev_run(loop(), 0); - } /* freeing resources */ free((void *)instance.name); free((void *)instance.config); diff --git a/test/app-luatest/gh_9411_fix_graceful_shutdown_break_on_script_exit_test.lua b/test/app-luatest/gh_9411_fix_graceful_shutdown_break_on_script_exit_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..fa86badaf4c43c7b825636384934a6611ca8f649 --- /dev/null +++ b/test/app-luatest/gh_9411_fix_graceful_shutdown_break_on_script_exit_test.lua @@ -0,0 +1,42 @@ +local popen = require('popen') +local t = require('luatest') + +local g = t.group() + +g.after_each(function() + if g.handle ~= nil then + g.handle:close() + end + g.handle = nil +end) + +g.test = function() + local script = [[ + local fiber = require('fiber') + + box.ctl.set_on_shutdown_timeout(1) + box.ctl.on_shutdown(function() + fiber.sleep(0.2) + print('shutdown callback finished') + end, nil) + + fiber.create(function() + os.exit(0) + end) + + fiber.sleep(0.1) + ]] + local tarantool_bin = arg[-1] + local handle, err = popen.new({tarantool_bin, '-e', script}, + {stdout = popen.opts.PIPE, + stdin = popen.opts.DEVNULL, + stderr = popen.opts.DEVNULL}) + assert(handle, err) + g.handle = handle + local output, err = handle:read({timeout = 3}) + assert(output, err) + t.assert_equals(output, 'shutdown callback finished\n') + local status = handle:wait() + t.assert_equals(status.state, 'exited') + t.assert_equals(status.exit_code, 0) +end