Skip to content
Snippets Groups Projects
Commit 8b380c93 authored by Roman Tsisyk's avatar Roman Tsisyk
Browse files

Fix #334: Warnings on startup

Tarantool's signal handlers are now installed *before* executing
Lua script. libreadline doesn't install own signals anymore.
TTY is now clean up properly in all cases.

This patch also fixes possible problems with signal handlers
after daemonization via box.cfg { background = true }.
parent 6d1b3e2d
No related merge requests found
......@@ -192,6 +192,15 @@ readline_cb(va_list ap)
{
const char **line = va_arg(ap, const char **);
const char *prompt = va_arg(ap, const char *);
/*
* libeio threads blocks all signals by default. Therefore, nobody
* can interrupt read(2) syscall inside readline() to correctly
* cleanup resources and restore terminal state. In case of signal
* a signal_cb(), a ev watcher in tarantool.cc will stop event
* loop and and stop entire process by exiting the main thread.
* rl_cleanup_after_signal() is called from tarantool_lua_free()
* in order to restore terminal state.
*/
*line = readline(prompt);
return 0;
}
......@@ -303,6 +312,12 @@ tarantool_lua_init(const char *tarantool_bin, int argc, char **argv)
luaopen_json(L);
lua_pop(L, 1);
/*
* Disable libreadline signals handlers. All signals are handled in
* main thread by libev watchers.
*/
rl_catch_signals = 0;
rl_catch_sigwinch = 0;
static const struct luaL_reg consolelib[] = {
{"readline", tarantool_console_readline},
{"add_history", tarantool_console_add_history},
......@@ -443,5 +458,10 @@ tarantool_lua_free()
lua_close(tarantool_L);
}
tarantool_L = NULL;
if (isatty(STDIN_FILENO)) {
/* See comments in readline_cb() */
rl_cleanup_after_signal();
}
}
......@@ -75,6 +75,7 @@ int main_argc;
/** Signals handled after start as part of the event loop. */
static ev_signal ev_sigs[4];
static const int ev_sig_count = sizeof(ev_sigs)/sizeof(*ev_sigs);
static bool start_loop = true;
extern const void *opt_def;
......@@ -153,6 +154,7 @@ signal_cb(ev_loop *loop, struct ev_signal *w, int revents)
(void) w;
(void) revents;
start_loop = false;
/* Terminate the main event loop */
ev_break(loop, EVBREAK_ALL);
}
......@@ -234,13 +236,6 @@ signal_free(void)
ev_signal_stop(loop(), &ev_sigs[i]);
}
static void
signal_start(void)
{
for (int i = 0; i < ev_sig_count; i++)
ev_signal_start(loop(), &ev_sigs[i]);
}
/** Make sure the child has a default signal disposition. */
static void
signal_reset()
......@@ -260,6 +255,9 @@ signal_reset()
sigaction(SIGFPE, &sa, NULL) == -1)
say_syserror("sigaction");
for (int i = 0; i < ev_sig_count; i++)
ev_signal_stop(loop(), &ev_sigs[i]);
/* Unblock any signals blocked by libev. */
sigset_t sigset;
sigfillset(&sigset);
......@@ -302,6 +300,8 @@ signal_init(void)
ev_signal_init(&ev_sigs[1], signal_cb, SIGINT);
ev_signal_init(&ev_sigs[2], signal_cb, SIGTERM);
ev_signal_init(&ev_sigs[3], signal_cb, SIGHUP);
for (int i = 0; i < ev_sig_count; i++)
ev_signal_start(loop(), &ev_sigs[i]);
(void) tt_pthread_atfork(NULL, NULL, signal_reset);
}
......@@ -367,6 +367,12 @@ background()
if (setsid() == -1)
goto error;
/*
* reinit signals after fork, because fork() implicitly calls
* signal_reset() via pthread_atfork() hook installed by signal_init().
*/
signal_init();
/* reinit coeio after fork (because libeio required it) */
coeio_reinit();
/*
......@@ -610,9 +616,6 @@ main(int argc, char **argv)
main_argc = argc;
main_argv = argv;
/* main core cleanup routine */
atexit(tarantool_free);
fiber_init();
/* Init iobuf library with default readahead */
iobuf_init();
......@@ -620,7 +623,9 @@ main(int argc, char **argv)
signal_init();
tarantool_lua_init(tarantool_bin, main_argc, main_argv);
bool start_loop = false;
/* main core cleanup routine */
atexit(tarantool_free);
try {
int events = ev_activecnt(loop());
/*
......@@ -630,12 +635,16 @@ main(int argc, char **argv)
* initialized.
*/
tarantool_lua_run_script(script);
start_loop = ev_activecnt(loop()) > events;
/*
* Start event loop after executing Lua script if signal_cb()
* wasn't triggered and there is some new events. Initial value
* of start_loop can be set to false by signal_cb().
*/
start_loop = start_loop && ev_activecnt(loop()) > events;
region_free(&fiber()->gc);
if (start_loop) {
say_crit("entering the event loop");
ev_now_update(loop());
signal_start();
ev_run(loop(), 0);
}
} catch (Exception *e) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment