From c26c254376f73d9b43dd1747746a2bc265a85bb3 Mon Sep 17 00:00:00 2001 From: LiFeng Date: Mon, 14 Jan 2019 04:29:40 -0500 Subject: [PATCH 021/140] lxc-attch: add error message Signed-off-by: LiFeng --- src/lxc/attach.c | 49 +++++++++++++++++++++++++++++++++++++++++----- src/lxc/attach.h | 4 ++-- src/lxc/attach_options.h | 6 +++--- src/lxc/conf.c | 27 +++++++++++++++++++++---- src/lxc/conf.h | 3 +++ src/lxc/lxccontainer.c | 4 ++-- src/lxc/tools/lxc_attach.c | 8 ++++---- src/lxc/tools/lxc_ls.c | 4 ++-- src/lxc/utils.c | 21 ++++++++++++++++++++ src/lxc/utils.h | 1 + 10 files changed, 105 insertions(+), 22 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 1886bde..570b9d0 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -757,10 +757,15 @@ static int attach_child_main(struct attach_clone_payload *payload) gid_t ns_root_gid = 0; lxc_attach_options_t* options = payload->options; struct lxc_proc_context_info* init_ctx = payload->init_ctx; + int msg_fd = -1; bool needs_lsm = (options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label; + /*isulad: record errpipe fd*/ + msg_fd = init_ctx->container->lxc_conf->errpipe[1]; + init_ctx->container->lxc_conf->errpipe[1] = -1; + /* A description of the purpose of this functionality is provided in the * lxc-attach(1) manual page. We have to remount here and not in the * parent process, otherwise /proc may not properly reflect the new pid @@ -980,7 +985,7 @@ static int attach_child_main(struct attach_clone_payload *payload) goto on_error; /* We're done, so we can now do whatever the user intended us to do. */ - _exit(payload->exec_function(payload->exec_payload)); + _exit(payload->exec_function(payload->exec_payload, msg_fd)); on_error: lxc_put_attach_clone_payload(payload); @@ -1085,7 +1090,7 @@ static inline void lxc_attach_terminal_close_log(struct lxc_terminal *terminal) int lxc_attach(const char *name, const char *lxcpath, lxc_attach_exec_t exec_function, void *exec_payload, - lxc_attach_options_t *options, pid_t *attached_process) + lxc_attach_options_t *options, pid_t *attached_process, char **err_msg) { int i, ret, status; int ipc_sockets[2]; @@ -1268,6 +1273,15 @@ int lxc_attach(const char *name, const char *lxcpath, return -1; } + + /* isulad: pipdfd for get error message of child or grandchild process. */ + if (pipe2(conf->errpipe, O_CLOEXEC) != 0) { + SYSERROR("Failed to init errpipe"); + free(cwd); + lxc_proc_put_context_info(init_ctx); + return -1; + } + /* Create intermediate subprocess, two reasons: * 1. We can't setns() in the child itself, since we want to make * sure we are properly attached to the pidns. @@ -1291,6 +1305,11 @@ int lxc_attach(const char *name, const char *lxcpath, /* close unneeded file descriptors */ close(ipc_sockets[1]); free(cwd); + + /* isulad: close errpipe */ + close(conf->errpipe[1]); + conf->errpipe[1] = -1; + lxc_proc_close_ns_fd(init_ctx); if (options->attach_flags & LXC_ATTACH_TERMINAL) lxc_attach_terminal_close_slave(&terminal); @@ -1399,6 +1418,19 @@ int lxc_attach(const char *name, const char *lxcpath, *attached_process = attached_pid; + /* isulad: read error msg from pipe */ + ssize_t size_read; + char errbuf[BUFSIZ + 1] = {0}; + + size_read = read(conf->errpipe[0], errbuf, BUFSIZ); + if (size_read > 0) { + if (err_msg) + *err_msg = strdup(errbuf); + if (!(*err_msg)) + ERROR("Out of memory"); + goto close_mainloop; + } + /* Now shut down communication with child, we're done. */ shutdown(ipc_sockets[0], SHUT_RDWR); close(ipc_sockets[0]); @@ -1439,7 +1471,11 @@ int lxc_attach(const char *name, const char *lxcpath, /* close unneeded file descriptors */ close(ipc_sockets[0]); - ipc_sockets[0] = -EBADF; + ipc_sockets[0] = -EBADF;\ + + /* isulad: close errpipe */ + close(conf->errpipe[0]); + conf->errpipe[0] = -1; if (options->attach_flags & LXC_ATTACH_TERMINAL) { lxc_attach_terminal_close_master(&terminal); @@ -1539,7 +1575,7 @@ int lxc_attach(const char *name, const char *lxcpath, _exit(0); } -int lxc_attach_run_command(void *payload) +int lxc_attach_run_command(void *payload, int msg_fd) { int ret = -1; lxc_attach_command_t *cmd = payload; @@ -1556,11 +1592,14 @@ int lxc_attach_run_command(void *payload) } } + /* isulad: write errorm messages */ + lxc_write_error_message(msg_fd, "exec: \"%s\": %s", cmd->program, strerror(errno)); + SYSERROR("Failed to exec \"%s\"", cmd->program); return ret; } -int lxc_attach_run_shell(void* payload) +int lxc_attach_run_shell(void* payload, int msg_fd) { uid_t uid; struct passwd pwent; diff --git a/src/lxc/attach.h b/src/lxc/attach.h index 4bf9578..e62b98b 100644 --- a/src/lxc/attach.h +++ b/src/lxc/attach.h @@ -42,7 +42,7 @@ struct lxc_proc_context_info { }; extern int lxc_attach(const char *name, const char *lxcpath, - lxc_attach_exec_t exec_function, void *exec_payload, - lxc_attach_options_t *options, pid_t *attached_process); + lxc_attach_exec_t exec_function, void *exec_payload, + lxc_attach_options_t *options, pid_t *attached_process, char **err_msg); #endif /* __LXC_ATTACH_H */ diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h index 081618c..7b0a8cb 100644 --- a/src/lxc/attach_options.h +++ b/src/lxc/attach_options.h @@ -71,7 +71,7 @@ enum { * * \return Function should return \c 0 on success, and any other value to denote failure. */ -typedef int (*lxc_attach_exec_t)(void* payload); +typedef int (*lxc_attach_exec_t)(void* payload, int msg_fd); /*! * LXC attach options for \ref lxc_container \c attach(). @@ -173,7 +173,7 @@ typedef struct lxc_attach_command_t { * * \return \c -1 on error, exit code of lxc_attach_command_t program on success. */ -extern int lxc_attach_run_command(void* payload); +extern int lxc_attach_run_command(void* payload, int msg_fd); /*! * \brief Run a shell command in the container. @@ -182,7 +182,7 @@ extern int lxc_attach_run_command(void* payload); * * \return Exit code of shell. */ -extern int lxc_attach_run_shell(void* payload); +extern int lxc_attach_run_shell(void* payload, int msg_fd); #ifdef __cplusplus } diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 537f956..8d8230f 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2803,10 +2803,6 @@ struct lxc_conf *lxc_conf_init(void) new->console.slave = -1; new->console.name[0] = '\0'; memset(&new->console.ringbuf, 0, sizeof(struct lxc_ringbuf)); - /* isulad init console fifos */ - new->console.init_fifo[0] = NULL; - new->console.init_fifo[1] = NULL; - lxc_list_init(&new->console.fifos); new->maincmd_fd = -1; new->nbd_idx = -1; new->rootfs.mount = strdup(default_rootfs_mount); @@ -2851,6 +2847,14 @@ struct lxc_conf *lxc_conf_init(void) lxc_list_init(&new->rootfs.maskedpaths); lxc_list_init(&new->rootfs.ropaths); new->exit_fd = -1; + /* isulad init console fifos */ + new->console.init_fifo[0] = NULL; + new->console.init_fifo[1] = NULL; + lxc_list_init(&new->console.fifos); + + new->errmsg = NULL; + new->errpipe[0] = -1; + new->errpipe[1] = -1; /* isulad add end */ return new; @@ -4280,6 +4284,19 @@ int lxc_clear_rootfs_ro_paths(struct lxc_conf *c) return 0; } +/*isulad: close error pipe */ +void lxc_close_error_pipe(int *errpipe) +{ + if (errpipe[0] >= 0) { + close(errpipe[0]); + errpipe[0] = -1; + } + if (errpipe[1] >= 0) { + close(errpipe[1]); + errpipe[1] = -1; + } +} + void lxc_conf_free(struct lxc_conf *conf) { if (!conf) @@ -4333,6 +4350,8 @@ void lxc_conf_free(struct lxc_conf *conf) free(conf->container_info_file); if (conf->exit_fd != -1) close(conf->exit_fd); + free(conf->errmsg); + lxc_close_error_pipe(conf->errpipe); /* isulad add end */ free(conf); } diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 7927812..db474e1 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -413,6 +413,9 @@ struct lxc_conf { char *container_info_file; int exit_fd; /* exit fifo fd*/ + + char *errmsg; /* record error messages */ + int errpipe[2];//pipdfd for get error message of child or grandchild process. /* isulad add end */ }; diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 8029f33..31f4819 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -4063,7 +4063,7 @@ static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_functio current_config = c->lxc_conf; - ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process); + ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process, &c->lxc_conf->errmsg); current_config = NULL; return ret; } @@ -4080,7 +4080,7 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options command.program = (char*)program; command.argv = (char**)argv; - r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid); + r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid, NULL); if (r < 0) { ERROR("ups"); return r; diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c index 6d0ffe5..a590fd1 100644 --- a/src/lxc/tools/lxc_attach.c +++ b/src/lxc/tools/lxc_attach.c @@ -295,8 +295,8 @@ static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *c wexit = ExitSignalOffset + signal; } out: - //if (c->lxc_conf->errmsg) - // *errmsg = strdup(c->lxc_conf->errmsg); + if (c->lxc_conf->errmsg) + *errmsg = strdup(c->lxc_conf->errmsg); return wexit; } @@ -376,8 +376,8 @@ static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *c else ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid); if (ret < 0) { - //if (c->lxc_conf->errmsg) - // lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg); + if (c->lxc_conf->errmsg) + lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg); close(msgpipe[1]); msgpipe[1] = -1; ret = -1; diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c index cb3eb1e..e261c7b 100644 --- a/src/lxc/tools/lxc_ls.c +++ b/src/lxc/tools/lxc_ls.c @@ -122,7 +122,7 @@ struct wrapargs { /* * Takes struct wrapargs as argument. */ -static int ls_get_wrapper(void *wrap); +static int ls_get_wrapper(void *wrap, int msgfd); /* * To calculate swap usage we should not simply check memory.usage_in_bytes and @@ -1023,7 +1023,7 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) return 0; } -static int ls_get_wrapper(void *wrap) +static int ls_get_wrapper(void *wrap, int msgfd) { int ret = -1; size_t len = 0; diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 74e74a1..8ec9f46 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -1971,3 +1971,24 @@ out: return startat; } +/* isulad: write error message */ +void lxc_write_error_message(int errfd, const char *format, ...) +{ + int ret; + char errbuf[BUFSIZ + 1] = {0}; + ssize_t sret; + va_list argp; + + if (errfd <= 0) + return; + + va_start(argp, format); + ret = vsnprintf(errbuf, BUFSIZ, format, argp); + va_end(argp); + if (ret < 0) + SYSERROR("Failed to call vsnprintf"); + sret = write(errfd, errbuf, strlen(errbuf)); + if (sret < 0) + SYSERROR("Write errbuf failed"); +} + diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 364bf67..3d56fd9 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -314,5 +314,6 @@ extern int lxc_setup_env_home(uid_t uid); extern int fd_nonblock(int fd); extern int unsigned long long lxc_get_process_startat(pid_t pid); +extern void lxc_write_error_message(int errfd, const char *format, ...); #endif /* __LXC_UTILS_H */ -- 1.8.3.1