lxc/0056-attach-add-sigfd-to-monitor-the-exit-of-pid.patch
lifeng 8966f1fe72 lxc: update lxc to 4.0.1
Signed-off-by: lifeng <lifeng68@huawei.com>
2020-04-23 19:30:12 +08:00

179 lines
5.6 KiB
Diff

From cb3a7926948c4d9668d54521cb7907436723b67a Mon Sep 17 00:00:00 2001
From: LiFeng <lifeng68@huawei.com>
Date: Wed, 22 Apr 2020 23:30:23 +0800
Subject: [PATCH] attach: add sigfd to monitor the exit of pid
Signed-off-by: LiFeng <lifeng68@huawei.com>
---
src/lxc/attach.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/lxc/terminal.c | 4 +--
2 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 51f5c08..b25222e 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -1197,6 +1197,56 @@ static int create_attach_timeout_thread(int64_t attach_timeout, pid_t pid)
out:
return ret;
}
+
+static int attach_signal_handler(int fd, uint32_t events, void *data,
+ struct lxc_epoll_descr *descr)
+{
+ int ret;
+ siginfo_t info;
+ pid_t *pid = data;
+
+ /* Check whether init is running. */
+ info.si_pid = 0;
+ ret = waitid(P_PID, *pid, &info, WEXITED | WNOWAIT | WNOHANG);
+ if (ret == 0 && info.si_pid == *pid) {
+ return log_error(LXC_MAINLOOP_CLOSE, "Container attach init process %d exited", *pid);
+ }
+
+ return LXC_MAINLOOP_CONTINUE;
+}
+
+static int isulad_setup_signal_fd(sigset_t *oldmask)
+{
+ int ret;
+ sigset_t mask;
+ const int signals[] = {SIGBUS, SIGILL, SIGSEGV, SIGWINCH};
+
+ /* Block everything except serious error signals. */
+ ret = sigfillset(&mask);
+ if (ret < 0)
+ return -EBADF;
+
+ for (int sig = 0; sig < (sizeof(signals) / sizeof(signals[0])); sig++) {
+ ret = sigdelset(&mask, signals[sig]);
+ if (ret < 0)
+ return -EBADF;
+ }
+
+ ret = pthread_sigmask(SIG_BLOCK, &mask, oldmask);
+ if (ret < 0)
+ return log_error_errno(-EBADF, errno,
+ "Failed to set signal mask");
+
+ ret = signalfd(-1, &mask, SFD_CLOEXEC);
+ if (ret < 0)
+ return log_error_errno(-EBADF,
+ errno, "Failed to create signal file descriptor");
+
+ TRACE("Created signal file descriptor %d", ret);
+
+ return ret;
+}
+
int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
void *exec_payload, lxc_attach_options_t *options,
pid_t *attached_process, char **err_msg)
@@ -1471,6 +1521,11 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
int ret_parent = -1;
pid_t to_cleanup_pid = pid;
struct lxc_epoll_descr descr = {0};
+#ifdef HAVE_ISULAD
+ int isulad_sigfd;
+ sigset_t isulad_oldmask;
+ struct lxc_epoll_descr isulad_descr = {0};
+#endif
/* close unneeded file descriptors */
close(ipc_sockets[1]);
@@ -1541,7 +1596,12 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
ret = lxc_attach_terminal_mainloop_init(&terminal, &descr);
if (ret < 0)
goto on_error;
+
#ifdef HAVE_ISULAD
+ ret = lxc_attach_terminal_mainloop_init(&terminal, &isulad_descr);
+ if (ret < 0)
+ goto on_error;
+
if (suffix != NULL) {
(void)lxc_exec_cmd_mainloop_add(&descr, &exec_command);
}
@@ -1549,6 +1609,16 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
TRACE("Initialized terminal mainloop");
}
+#ifdef HAVE_ISULAD
+ /* The signal fd has to be created before forking otherwise if the child
+ * process exits before we setup the signal fd, the event will be lost
+ * and the command will be stuck.
+ */
+ isulad_sigfd = isulad_setup_signal_fd(&isulad_oldmask);
+ if (isulad_sigfd < 0)
+ goto close_mainloop;
+#endif
+
/* Let the child process know to go ahead. */
status = 0;
ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
@@ -1637,6 +1707,7 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
/* isulad: read error msg from pipe */
ssize_t size_read;
char errbuf[BUFSIZ + 1] = {0};
+ pid_t tmp_pid = *attached_process;
size_read = read(conf->errpipe[0], errbuf, BUFSIZ);
if (size_read > 0) {
@@ -1644,6 +1715,13 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
*err_msg = safe_strdup(errbuf);
goto close_mainloop;
}
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ ret = lxc_mainloop_add_handler(&descr, isulad_sigfd, attach_signal_handler, &tmp_pid);
+ if (ret < 0) {
+ ERROR("Failed to add signal handler for %d to mainloop", tmp_pid);
+ goto close_mainloop;
+ }
+ }
#endif
/* Now shut down communication with child, we're done. */
@@ -1672,13 +1750,19 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
}
#ifdef HAVE_ISULAD
+ // do lxc_mainloop to make sure we do not lose any output
+ (void)lxc_mainloop(&isulad_descr, 100);
if (g_attach_timeout_state == ATTACH_TIMEOUT && err_msg != NULL && *err_msg == NULL) {
*err_msg = safe_strdup("Attach exceeded timeout");
}
#endif
close_mainloop:
- if (options->attach_flags & LXC_ATTACH_TERMINAL)
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+#ifdef HAVE_ISULAD
+ lxc_mainloop_close(&isulad_descr);
+#endif
lxc_mainloop_close(&descr);
+ }
on_error:
if (ipc_sockets[0] >= 0) {
diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c
index 0197503..e696b4e 100644
--- a/src/lxc/terminal.c
+++ b/src/lxc/terminal.c
@@ -763,11 +763,11 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
/* notes: do not close the master fd due to if we close the fd, the process may
* recive SIGHUP and the exit code will be 141 (128 + 13)
*/
- return LXC_MAINLOOP_CLOSE;
+ return LXC_MAINLOOP_CONTINUE;
} else if (fd == terminal->pipes[0][1]) {
TRACE("closed stdin pipe of container stdin");
terminal->pipes[0][1] = -EBADF;
- return LXC_MAINLOOP_CLOSE;
+ return LXC_MAINLOOP_CONTINUE;
} else {
ERROR("Handler received unexpected file descriptor");
}
--
1.8.3.1