179 lines
5.6 KiB
Diff
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
|
||
|
|
|