Merge pull request #1409 from giuseppe/conmon-catch-signals

conmon: catch SIGTERM, SIGINT and SIGQUIT
This commit is contained in:
Daniel J Walsh 2018-03-07 21:28:35 +00:00 committed by GitHub
commit c189b8d147
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -123,6 +123,8 @@ static inline void strv_cleanup(char ***strv)
#define DEFAULT_SOCKET_PATH "/var/lib/crio" #define DEFAULT_SOCKET_PATH "/var/lib/crio"
static volatile pid_t container_pid = -1;
static volatile pid_t create_pid = -1;
static bool opt_version = false; static bool opt_version = false;
static bool opt_terminal = false; static bool opt_terminal = false;
static bool opt_stdin = false; static bool opt_stdin = false;
@ -644,7 +646,25 @@ static bool read_stdio(int fd, stdpipe_t pipe, bool *eof)
static void on_sigchld(G_GNUC_UNUSED int signal) static void on_sigchld(G_GNUC_UNUSED int signal)
{ {
raise (SIGUSR1); raise(SIGUSR1);
}
static void on_sig_exit(int signal)
{
if (container_pid > 0) {
if (kill(container_pid, signal) == 0)
return;
} else if (create_pid > 0) {
if (kill(create_pid, signal) == 0)
return;
if (errno == ESRCH) {
/* The create_pid process might have exited, so try container_pid again. */
if (container_pid > 0 && kill(container_pid, signal) == 0)
return;
}
}
/* Just force a check if we get here. */
raise(SIGUSR1);
} }
static void check_child_processes(GHashTable *pid_to_handler) static void check_child_processes(GHashTable *pid_to_handler)
@ -938,6 +958,7 @@ static void
runtime_exit_cb (G_GNUC_UNUSED GPid pid, int status, G_GNUC_UNUSED gpointer user_data) runtime_exit_cb (G_GNUC_UNUSED GPid pid, int status, G_GNUC_UNUSED gpointer user_data)
{ {
runtime_status = status; runtime_status = status;
create_pid = -1;
g_main_loop_quit (main_loop); g_main_loop_quit (main_loop);
} }
@ -946,6 +967,7 @@ container_exit_cb (G_GNUC_UNUSED GPid pid, int status, G_GNUC_UNUSED gpointer us
{ {
ninfof("container %d exited with status %d", pid, status); ninfof("container %d exited with status %d", pid, status);
container_status = status; container_status = status;
container_pid = -1;
g_main_loop_quit (main_loop); g_main_loop_quit (main_loop);
} }
@ -1152,8 +1174,7 @@ int main(int argc, char *argv[])
_cleanup_free_ char *csname = NULL; _cleanup_free_ char *csname = NULL;
GError *err = NULL; GError *err = NULL;
_cleanup_free_ char *contents = NULL; _cleanup_free_ char *contents = NULL;
int container_pid = -1; pid_t main_pid;
pid_t main_pid, create_pid;
/* Used for !terminal cases. */ /* Used for !terminal cases. */
int slavefd_stdin = -1; int slavefd_stdin = -1;
int slavefd_stdout = -1; int slavefd_stdout = -1;
@ -1363,6 +1384,10 @@ int main(int argc, char *argv[])
add_argv(runtime_argv, opt_cid, NULL); add_argv(runtime_argv, opt_cid, NULL);
end_argv(runtime_argv); end_argv(runtime_argv);
sigset_t mask, oldmask;
if ((sigemptyset(&mask) < 0) || (sigaddset(&mask, SIGTERM) < 0) || (sigaddset(&mask, SIGQUIT) < 0)
|| (sigaddset(&mask, SIGINT) < 0) || sigprocmask (SIG_BLOCK, &mask, &oldmask) < 0)
pexit("Failed to block signals");
/* /*
* We have to fork here because the current runC API dups the stdio of the * We have to fork here because the current runC API dups the stdio of the
* calling process over the container's fds. This is actually *very bad* * calling process over the container's fds. This is actually *very bad*
@ -1377,6 +1402,11 @@ int main(int argc, char *argv[])
pexit("Failed to fork the create command"); pexit("Failed to fork the create command");
} else if (!create_pid) { } else if (!create_pid) {
/* FIXME: This results in us not outputting runc error messages to crio's log. */ /* FIXME: This results in us not outputting runc error messages to crio's log. */
if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
pexit("Failed to set PDEATHSIG");
if (sigprocmask (SIG_SETMASK, &oldmask, NULL) < 0)
pexit("Failed to unblock signals");
if (slavefd_stdin < 0) if (slavefd_stdin < 0)
slavefd_stdin = dev_null_r; slavefd_stdin = dev_null_r;
if (dup2(slavefd_stdin, STDIN_FILENO) < 0) if (dup2(slavefd_stdin, STDIN_FILENO) < 0)
@ -1396,6 +1426,12 @@ int main(int argc, char *argv[])
exit(127); exit(127);
} }
if ((signal(SIGTERM, on_sig_exit) == SIG_ERR) || (signal(SIGQUIT, on_sig_exit) == SIG_ERR) || (signal(SIGINT, on_sig_exit) == SIG_ERR))
pexit("Failed to register the signal handler");
if (sigprocmask (SIG_SETMASK, &oldmask, NULL) < 0)
pexit("Failed to unblock signals");
if (opt_exit_command) if (opt_exit_command)
atexit(do_exit_command); atexit(do_exit_command);
@ -1408,13 +1444,13 @@ int main(int argc, char *argv[])
/* Map pid to its handler. */ /* Map pid to its handler. */
GHashTable *pid_to_handler = g_hash_table_new (g_int_hash, g_int_equal); GHashTable *pid_to_handler = g_hash_table_new (g_int_hash, g_int_equal);
g_hash_table_insert (pid_to_handler, &create_pid, runtime_exit_cb); g_hash_table_insert (pid_to_handler, (pid_t *) &create_pid, runtime_exit_cb);
/* /*
* Glib does not support SIGCHLD so use SIGUSR1 with the same semantic. We will * Glib does not support SIGCHLD so use SIGUSR1 with the same semantic. We will
* catch SIGCHLD and raise(SIGUSR1) in the signal handler. * catch SIGCHLD and raise(SIGUSR1) in the signal handler.
*/ */
g_unix_signal_add (SIGUSR1, on_sigusr1_cb, pid_to_handler); g_unix_signal_add(SIGUSR1, on_sigusr1_cb, pid_to_handler);
if (signal(SIGCHLD, on_sigchld) == SIG_ERR) if (signal(SIGCHLD, on_sigchld) == SIG_ERR)
pexit("Failed to set handler for SIGCHLD"); pexit("Failed to set handler for SIGCHLD");
@ -1470,7 +1506,7 @@ int main(int argc, char *argv[])
container_pid = atoi(contents); container_pid = atoi(contents);
ninfof("container PID: %d", container_pid); ninfof("container PID: %d", container_pid);
g_hash_table_insert (pid_to_handler, &container_pid, container_exit_cb); g_hash_table_insert (pid_to_handler, (pid_t *) &container_pid, container_exit_cb);
/* Setup endpoint for attach */ /* Setup endpoint for attach */
_cleanup_free_ char *attach_symlink_dir_path = NULL; _cleanup_free_ char *attach_symlink_dir_path = NULL;