From 9502363455188344dcfd7d1202cd48b7b554a5de Mon Sep 17 00:00:00 2001 From: Li Feng Date: Wed, 20 Jan 2021 14:22:33 +0800 Subject: [PATCH 18/18] IO: fix io data miss when exec with pipes Signed-off-by: Li Feng --- src/lxc/attach.c | 4 ++-- src/lxc/mainloop.c | 14 ++++++++++++++ src/lxc/mainloop.h | 2 ++ src/lxc/start.c | 4 ++-- src/lxc/terminal.c | 12 ++++++++---- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 87e23c229..c5fc56150 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -1754,7 +1754,7 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, } #endif if (options->attach_flags & LXC_ATTACH_TERMINAL) { - ret = lxc_mainloop(&descr, -1); + ret = isulad_safe_mainloop(&descr, -1); if (ret < 0) { ret_parent = -1; to_cleanup_pid = attached_pid; @@ -1763,7 +1763,7 @@ 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); + (void)isulad_safe_mainloop(&isulad_descr, 100); if (g_attach_timeout_state == ATTACH_TIMEOUT && err_msg != NULL && *err_msg == NULL) { *err_msg = safe_strdup("Attach exceeded timeout"); } diff --git a/src/lxc/mainloop.c b/src/lxc/mainloop.c index 6d4c5935a..35186f4b5 100644 --- a/src/lxc/mainloop.c +++ b/src/lxc/mainloop.c @@ -141,3 +141,17 @@ void lxc_mainloop_close(struct lxc_epoll_descr *descr) close_prot_errno_disarm(descr->epfd); } + +int isulad_safe_mainloop(struct lxc_epoll_descr *descr, int timeout_ms) +{ + int ret; + + ret = lxc_mainloop(descr, timeout_ms); + + // There are stdout and stderr channels, and two epolls should be performed to prevent + // one of the channels from exiting first, causing the other channel to not receive data, + // resulting in data loss + (void)lxc_mainloop(descr, 100); + + return ret; +} \ No newline at end of file diff --git a/src/lxc/mainloop.h b/src/lxc/mainloop.h index 8afac60d3..dad79188c 100644 --- a/src/lxc/mainloop.h +++ b/src/lxc/mainloop.h @@ -34,4 +34,6 @@ extern void lxc_mainloop_close(struct lxc_epoll_descr *descr); define_cleanup_function(struct lxc_epoll_descr *, lxc_mainloop_close); +extern int isulad_safe_mainloop(struct lxc_epoll_descr *descr, int timeout_ms); + #endif diff --git a/src/lxc/start.c b/src/lxc/start.c index 50a1a8203..e6e217042 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -590,13 +590,13 @@ int lxc_poll(const char *name, struct lxc_handler *handler) } #endif - ret = lxc_mainloop(&descr, -1); + ret = isulad_safe_mainloop(&descr, -1); close_prot_errno_disarm(descr.epfd); if (ret < 0 || !handler->init_died) goto out_mainloop_console; if (has_console) - ret = lxc_mainloop(&descr_console, 100); + ret = isulad_safe_mainloop(&descr_console, 100); out_mainloop_console: if (has_console) { diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c index a4c6ad0c8..1e467f5a6 100644 --- a/src/lxc/terminal.c +++ b/src/lxc/terminal.c @@ -679,19 +679,22 @@ static void lxc_forward_data_to_fifo(struct lxc_list *list, bool is_err, const c struct lxc_list *it = NULL; struct lxc_list *next = NULL; struct lxc_fifos_fd *elem = NULL; + ssize_t w = 0; lxc_list_for_each_safe(it, list, next) { elem = it->elem; if (is_err) { if (elem->err_fd >= 0) { - if (lxc_write_nointr_for_fifo(elem->err_fd, buf, r) < 0) { - ERROR("Failed to write to fifo fd %d with error: %s", elem->err_fd, strerror(errno)); + w = lxc_write_nointr_for_fifo(elem->err_fd, buf, r); + if (w != r) { + WARN("Failed to write to fifo fd %d with error: %s", elem->err_fd, strerror(errno)); } } } else { if (elem->out_fd >= 0) { - if (lxc_write_nointr_for_fifo(elem->out_fd, buf, r) < 0) { - ERROR("Failed to write to fifo fd %d with error: %s", elem->out_fd, strerror(errno)); + w = lxc_write_nointr_for_fifo(elem->out_fd, buf, r); + if (w != r) { + WARN("Failed to write to fifo fd %d with error: %s", elem->out_fd, strerror(errno)); } } } @@ -1673,6 +1676,7 @@ int lxc_terminal_create(struct lxc_terminal *terminal) ERROR("Failed to create stdin pipe"); goto err; } + /* for stdout */ if (pipe2(terminal->pipes[1], O_CLOEXEC)) { ERROR("Failed to create stdout pipe"); -- 2.25.1