From 0dc9bee69873493576be01fe001e17211b46ad87 Mon Sep 17 00:00:00 2001 From: tanyifeng Date: Wed, 16 Jan 2019 14:38:38 +0800 Subject: [PATCH 039/138] print error message when container start failed Signed-off-by: tanyifeng Signed-off-by: LiFeng --- src/lxc/attach.c | 6 +-- src/lxc/cgroups/cgfsng.c | 22 +++++++-- src/lxc/cgroups/cgroup.c | 4 +- src/lxc/cgroups/cgroup.h | 2 + src/lxc/conf.c | 122 ++++++++++++++++++++++++++-------------------- src/lxc/conf.h | 5 +- src/lxc/execute.c | 3 +- src/lxc/lxccontainer.c | 37 ++++++++++++-- src/lxc/start.c | 14 ++++-- src/lxc/start.h | 2 +- src/lxc/tools/lxc_start.c | 3 ++ 11 files changed, 147 insertions(+), 73 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 4ccdd74..b44ea74 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -1396,7 +1396,7 @@ int lxc_attach(const char *name, const char *lxcpath, /* Setup resource limits */ if (!lxc_list_empty(&conf->limits)) { - ret = setup_resource_limits(&conf->limits, pid); + ret = setup_resource_limits(&conf->limits, pid, -1); if (ret < 0) goto on_error; } @@ -1650,8 +1650,8 @@ int lxc_attach_run_command(void *payload, int msg_fd) } } - /* isulad: write errorm messages */ - lxc_write_error_message(msg_fd, "exec: \"%s\": %s", cmd->program, strerror(errno)); + /* isulad: write error messages */ + lxc_write_error_message(msg_fd, "exec: \"%s\": %s.", cmd->program, strerror(errno)); SYSERROR("Failed to exec \"%s\"", cmd->program); return ret; diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index bc1481d..47b12a6 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -1236,7 +1236,7 @@ static int mkdir_eexist_on_last(const char *dir, mode_t mode) return 0; } -static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname) +static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, int errfd) { int ret; @@ -1244,8 +1244,8 @@ static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname) if (file_exists(h->container_full_path)) { // it must not already exist ERROR("Cgroup path \"%s\" already exist.", h->container_full_path); - //lxc_write_error_message(errfd, "%s:%d: Cgroup path \"%s\" already exist.", - // __FILE__, __LINE__, h->fullcgpath); + lxc_write_error_message(errfd, "%s:%d: Cgroup path \"%s\" already exist.", + __FILE__, __LINE__, h->container_full_path); return false; } @@ -1288,7 +1288,7 @@ __cgfsng_ops static bool cgfsng_payload_create(struct cgroup_ops *ops, } for (i = 0; ops->hierarchies[i]; i++) { - if (!create_path_for_hierarchy(ops->hierarchies[i], container_cgroup)) { + if (!create_path_for_hierarchy(ops->hierarchies[i], container_cgroup, ops->errfd)) { SYSERROR("Failed to create %s", ops->hierarchies[i]->container_full_path); return false; } @@ -2203,6 +2203,11 @@ static int cg_legacy_set_data(struct cgroup_ops *ops, const char *filename, fullpath = must_make_path(h->container_full_path, filename, NULL); ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666); + if (ret) { + lxc_write_error_message(ops->errfd, + "%s:%d: setting cgroup config for ready process caused \"failed to write %s to %s: %s\".", + __FILE__, __LINE__, value, fullpath, strerror(errno)); + } free(fullpath); return ret; } @@ -2294,9 +2299,15 @@ static bool __cg_legacy_setup_limits(struct cgroup_ops *ops, } if (setvalue > readvalue) { ERROR("The maximum allowed cpu-shares is %s", value); + lxc_write_error_message(ops->errfd, + "%s:%d: setting cgroup config for ready process caused \"The maximum allowed cpu-shares is %s\".", + __FILE__, __LINE__, value); goto out; } else if (setvalue < readvalue) { ERROR("The minimum allowed cpu-shares is %s", value); + lxc_write_error_message(ops->errfd, + "%s:%d: setting cgroup config for ready process caused \"The minimum allowed cpu-shares is %s\".", + __FILE__, __LINE__, value); goto out; } } @@ -2699,7 +2710,7 @@ __cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops, struct lxc_han return true; } -struct cgroup_ops *cgfsng_ops_init(void) +struct cgroup_ops *cgfsng_ops_init(int errfd) { struct cgroup_ops *cgfsng_ops; @@ -2715,6 +2726,7 @@ struct cgroup_ops *cgfsng_ops_init(void) return NULL; } + cgfsng_ops->errfd = errfd; cgfsng_ops->data_init = cgfsng_data_init; cgfsng_ops->destroy = cgfsng_payload_destroy; cgfsng_ops->payload_create = cgfsng_payload_create; diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c index 8e7aef9..7442c31 100644 --- a/src/lxc/cgroups/cgroup.c +++ b/src/lxc/cgroups/cgroup.c @@ -38,13 +38,13 @@ lxc_log_define(cgroup, lxc); -extern struct cgroup_ops *cgfsng_ops_init(void); +extern struct cgroup_ops *cgfsng_ops_init(int errfd); struct cgroup_ops *cgroup_init(struct lxc_handler *handler) { struct cgroup_ops *cgroup_ops; - cgroup_ops = cgfsng_ops_init(); + cgroup_ops = cgfsng_ops_init(handler->conf->errpipe[1]); if (!cgroup_ops) { ERROR("Failed to initialize cgroup driver"); return NULL; diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h index fa4871e..b6116f6 100644 --- a/src/lxc/cgroups/cgroup.h +++ b/src/lxc/cgroups/cgroup.h @@ -92,6 +92,8 @@ struct cgroup_ops { char **cgroup_use; char *cgroup_pattern; char *container_cgroup; + /* isulad: errfd */ + int errfd; /* @hierarchies * - A NULL-terminated array of struct hierarchy, one per legacy diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 88cebfd..8fa63f7 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2414,6 +2414,8 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, ret = mkdir_p(path, 0755); if (ret < 0 && errno != EEXIST) { SYSERROR("Failed to create directory \"%s\"", path); + lxc_write_error_message(rootfs->errfd, "%s:%d: mkdir %s: %s.", + __FILE__, __LINE__, path, strerror(errno)); return -1; } } @@ -2435,12 +2437,17 @@ static int mount_entry_create_dir_file(const struct mntent *mntent, free(p1); if (ret < 0 && errno != EEXIST) { SYSERROR("Failed to create directory \"%s\"", path); + lxc_write_error_message(rootfs->errfd, "%s:%d: mkdir %s: %s.", + __FILE__, __LINE__, p2, strerror(errno)); return -1; } ret = mknod(path, S_IFREG | 0000, 0); - if (ret < 0 && errno != EEXIST) + if (ret < 0 && errno != EEXIST) { + lxc_write_error_message(rootfs->errfd, "%s:%d: open %s: %s.", + __FILE__, __LINE__, path, strerror(errno)); return -errno; + } return 0; } @@ -2550,7 +2557,9 @@ static inline int mount_entry_on_generic(struct mntent *mntent, if (rootfs_path) { rpath = follow_symlink_in_scope(path, rootfs_path); if (!rpath) { - ERROR("Failed to get real path for '%s'", path); + ERROR("Failed to get real path of '%s' in scope '%s'.", path, rootfs_path); + lxc_write_error_message(rootfs->errfd, "%s:%d: failed to get real path of '%s' in scope '%s'.", + __FILE__, __LINE__, path, rootfs_path); return -1; } dest = rpath; @@ -2558,6 +2567,8 @@ static inline int mount_entry_on_generic(struct mntent *mntent, ret = check_mount_destination(rootfs_path, dest); if (ret) { ERROR("Mount destination is invalid: '%s'", dest); + lxc_write_error_message(rootfs->errfd, "%s:%d: mount destination is invalid: '%s'.", + __FILE__, __LINE__, dest); free(rpath); return -1; } @@ -2587,6 +2598,10 @@ static inline int mount_entry_on_generic(struct mntent *mntent, ret = mount_entry(mntent->mnt_fsname, dest, mntent->mnt_type, mntflags, pflags, mntdata, optional, dev, relative, rootfs_path); } + if (ret < 0) { + lxc_write_error_message(rootfs->errfd, "%s:%d: failed to mount %s as type %s.", + __FILE__, __LINE__, mntent->mnt_fsname, mntent->mnt_type); + } free(mntdata); free(rpath); @@ -2949,7 +2964,7 @@ static int parse_resource(const char *res) return resid; } -int setup_resource_limits(struct lxc_list *limits, pid_t pid) +int setup_resource_limits(struct lxc_list *limits, pid_t pid, int errfd) { int resid; struct lxc_list *it; @@ -2966,7 +2981,10 @@ int setup_resource_limits(struct lxc_list *limits, pid_t pid) #if HAVE_PRLIMIT || HAVE_PRLIMIT64 if (prlimit(pid, resid, &lim->limit, NULL) != 0) { - SYSERROR("Failed to set limit %s", lim->resource); + SYSERROR("Failed to set limit %s %lu %lu.", lim->resource, lim->limit.rlim_cur, lim->limit.rlim_max); + lxc_write_error_message(errfd, "%s:%d: Failed to set limit %s %lu %lu: %s.", + __FILE__, __LINE__, lim->resource, + lim->limit.rlim_cur, lim->limit.rlim_max, strerror(errno)); return -1; } @@ -3989,6 +4007,8 @@ int lxc_setup(struct lxc_handler *handler) ret = lxc_setup_rootfs_prepare_root(lxc_conf, name, lxcpath); if (ret < 0) { ERROR("Failed to setup rootfs"); + lxc_write_error_message(lxc_conf->errpipe[1], "%s:%d: failed to setup rootfs %s.", + __FILE__, __LINE__, lxc_conf->rootfs.path); return -1; } @@ -3996,31 +4016,31 @@ int lxc_setup(struct lxc_handler *handler) ret = setup_utsname(lxc_conf->utsname); if (ret < 0) { ERROR("Failed to setup the utsname %s", name); - return -1; + goto on_error; } } ret = lxc_setup_keyring(); if (ret < 0) - return -1; + goto on_error; ret = lxc_setup_network_in_child_namespaces(lxc_conf, &lxc_conf->network); if (ret < 0) { ERROR("Failed to setup network"); - return -1; + goto on_error; } ret = lxc_network_send_name_and_ifindex_to_parent(handler); if (ret < 0) { ERROR("Failed to send network device names and ifindices to parent"); - return -1; + goto on_error; } if (lxc_conf->autodev > 0) { ret = mount_autodev(name, &lxc_conf->rootfs, lxcpath); if (ret < 0) { ERROR("Failed to mount \"/dev\""); - return -1; + goto on_error; } } @@ -4030,13 +4050,14 @@ int lxc_setup(struct lxc_handler *handler) ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler); if (ret < 0) { ERROR("Failed to setup first automatic mounts"); - return -1; + goto on_error; } + lxc_conf->rootfs.errfd = lxc_conf->errpipe[1]; ret = setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath); if (ret < 0) { ERROR("Failed to setup mounts"); - return -1; + goto on_error; } if (lxc_conf->is_execute) { @@ -4047,13 +4068,13 @@ int lxc_setup(struct lxc_handler *handler) ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static"); if (ret < 0 || ret >= PATH_MAX) { ERROR("Path to init.lxc.static too long"); - return -1; + goto on_error; } fd = open(path, O_PATH | O_CLOEXEC); if (fd < 0) { SYSERROR("Unable to open lxc.init.static"); - return -1; + goto on_error; } ((struct execute_args *)handler->data)->init_fd = fd; @@ -4062,7 +4083,7 @@ int lxc_setup(struct lxc_handler *handler) ret = lxc_execute_bind_init(handler); if (ret < 0) { ERROR("Failed to bind-mount the lxc init system"); - return -1; + goto on_error; } } } @@ -4074,7 +4095,7 @@ int lxc_setup(struct lxc_handler *handler) ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler); if (ret < 0) { ERROR("Failed to setup remaining automatic mounts"); - return -1; + goto on_error; } /*isulad: move mount entries here, before we do lxc_fill_autodev and populate devices */ @@ -4083,27 +4104,27 @@ int lxc_setup(struct lxc_handler *handler) &lxc_conf->mount_list, name, lxcpath); if (ret < 0) { ERROR("Failed to setup mount entries"); - return -1; + goto on_error; } } ret = run_lxc_hooks(name, "mount", lxc_conf, NULL); if (ret < 0) { ERROR("Failed to run mount hooks"); - return -1; + goto on_error; } if (lxc_conf->autodev > 0) { ret = run_lxc_hooks(name, "autodev", lxc_conf, NULL); if (ret < 0) { ERROR("Failed to run autodev hooks"); - return -1; + goto on_error; } ret = lxc_fill_autodev(&lxc_conf->rootfs); if (ret < 0) { ERROR("Failed to populate \"/dev\""); - return -1; + goto on_error; } } @@ -4111,64 +4132,64 @@ int lxc_setup(struct lxc_handler *handler) if (!lxc_list_empty(&lxc_conf->populate_devs)) { if (setup_populate_devs(&lxc_conf->rootfs, &lxc_conf->populate_devs)) { ERROR("Failed to setup devices in the container"); - return -1;; + goto on_error; } } /* Make sure any start hooks are in the container */ if (!verify_start_hooks(lxc_conf)) { ERROR("Failed to verify start hooks"); - return -1; + goto on_error; } ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttys.dir); if (ret < 0) { ERROR("Failed to setup console"); - return -1; + goto on_error; } ret = lxc_setup_dev_symlinks(&lxc_conf->rootfs); if (ret < 0) { ERROR("Failed to setup \"/dev\" symlinks"); - return -1; + goto on_error; } ret = lxc_create_tmp_proc_mount(lxc_conf); if (ret < 0) { ERROR("Failed to \"/proc\" LSMs"); - return -1; + goto on_error; } ret = lxc_setup_rootfs_switch_root(&lxc_conf->rootfs); if (ret < 0) { ERROR("Failed to pivot root into rootfs"); - return -1; + goto on_error; } /* isulad: remount rootfs readonly if necessary */ if (setup_rootfs_mountopts(&lxc_conf->rootfs)) { ERROR("failed to set rootfs for '%s'", name); - return -1; + goto on_error; } if (lxc_conf->rootfs.path) { ret = lxc_setup_devpts(lxc_conf); if (ret < 0) { ERROR("Failed to setup new devpts instance"); - return -1; + goto on_error; } } ret = lxc_create_ttys(handler); if (ret < 0) - return -1; + goto on_error; //isulad: setup rootfs masked paths if (!lxc_list_empty(&lxc_conf->rootfs.maskedpaths)) { if (setup_rootfs_maskedpaths(&lxc_conf->rootfs.maskedpaths)) { ERROR("failed to setup maskedpaths"); - return -1; + goto on_error; } } @@ -4176,7 +4197,7 @@ int lxc_setup(struct lxc_handler *handler) if (!lxc_list_empty(&lxc_conf->rootfs.ropaths)) { if (setup_rootfs_ropaths(&lxc_conf->rootfs.ropaths)) { ERROR("failed to setup readonlypaths"); - return -1; + goto on_error; } } @@ -4186,7 +4207,7 @@ int lxc_setup(struct lxc_handler *handler) ret = setup_personality(lxc_conf->personality); if (ret < 0) { ERROR("Failed to set personality"); - return -1; + goto on_error; } /* Set sysctl value to a path under /proc/sys as determined from the @@ -4197,7 +4218,7 @@ int lxc_setup(struct lxc_handler *handler) ret = setup_sysctl_parameters(&lxc_conf->sysctls); if (ret < 0) { ERROR("Failed to setup sysctl parameters"); - return -1; + goto on_error; } } @@ -4206,21 +4227,24 @@ int lxc_setup(struct lxc_handler *handler) ERROR("Container requests lxc.cap.drop and " "lxc.cap.keep: either use lxc.cap.drop or " "lxc.cap.keep, not both"); - return -1; + goto on_error; } if (dropcaps_except(&lxc_conf->keepcaps)) { ERROR("Failed to keep capabilities"); - return -1; + goto on_error; } } else if (setup_caps(&lxc_conf->caps)) { ERROR("Failed to drop capabilities"); - return -1; + goto on_error; } NOTICE("The container \"%s\" is set up", name); return 0; +on_error: + lxc_write_error_message(lxc_conf->errpipe[1], "Failed to setup lxc, please check the config file."); + return -1; } /* isulad drop caps for container*/ @@ -4555,11 +4579,9 @@ void* wait_ocihook_timeout(void *arg) __FILE__, __LINE__, lxchook_names[conf->which], (double)conf->timeout); - if (conf->errfd >= 0) { - lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\"", - __FILE__, __LINE__, lxchook_names[conf->which], - (double)conf->timeout); - } + lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"hook ran past specified timeout of %.1fs\".", + __FILE__, __LINE__, lxchook_names[conf->which], + (double)conf->timeout); if (kill(conf->pid, SIGKILL) && errno != ESRCH) { ERROR("Send kill signal failed"); @@ -4640,22 +4662,18 @@ static int run_ocihook_buffer(struct oci_hook_conf *oconf, char *inmsg) goto print_hook; } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) { ERROR("Script exited with status %d. output:%s", WEXITSTATUS(ret), output); - if (conf->errfd >= 0) { - lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output:%s\"", - __FILE__, __LINE__, - (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], - WEXITSTATUS(ret), output); - } + lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: exit status %d, output:%s\".", + __FILE__, __LINE__, + (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], + WEXITSTATUS(ret), output); goto print_hook; } else if (WIFSIGNALED(ret)) { ERROR("Script terminated by signal %d.", WTERMSIG(ret)); - if (conf->errfd >= 0) { - lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: Script terminated by signal %d\"", - __FILE__, __LINE__, - (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], - WTERMSIG(ret)); - } + lxc_write_error_message(conf->errfd, "%s:%d: running %s hook caused \"error running hook: Script terminated by signal %d\".", + __FILE__, __LINE__, + (conf->which >= NUM_LXC_HOOKS) ? "invalid type" : lxchook_names[conf->which], + WTERMSIG(ret)); goto print_hook; } diff --git a/src/lxc/conf.h b/src/lxc/conf.h index b92c48e..88f5b41 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -175,6 +175,8 @@ struct lxc_rootfs { struct lxc_list maskedpaths; /* isulad: ropaths */ struct lxc_list ropaths; + /* isulad: errfd */ + int errfd; }; /* @@ -462,7 +464,7 @@ extern int lxc_setup_rootfs_prepare_root(struct lxc_conf *conf, const char *name, const char *lxcpath); extern int lxc_setup(struct lxc_handler *handler); extern int lxc_setup_parent(struct lxc_handler *handler); -extern int setup_resource_limits(struct lxc_list *limits, pid_t pid); +extern int setup_resource_limits(struct lxc_list *limits, pid_t pid, int errfd); extern int find_unmapped_nsid(struct lxc_conf *conf, enum idtype idtype); extern int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype); @@ -499,6 +501,7 @@ int lxc_clear_populate_devices(struct lxc_conf *c); int lxc_clear_rootfs_masked_paths(struct lxc_conf *c); int lxc_clear_rootfs_ro_paths(struct lxc_conf *c); int lxc_drop_caps(struct lxc_conf *conf); +void lxc_close_error_pipe(int *errpipe); /* isulad add end */ diff --git a/src/lxc/execute.c b/src/lxc/execute.c index d388e63..3fc46c6 100644 --- a/src/lxc/execute.c +++ b/src/lxc/execute.c @@ -40,7 +40,7 @@ lxc_log_define(execute, start); -static int execute_start(struct lxc_handler *handler, void* data) +static int execute_start(struct lxc_handler *handler, void* data, int fd) { int argc_add, j; char **argv; @@ -91,6 +91,7 @@ static int execute_start(struct lxc_handler *handler, void* data) else execvp(argv[0], argv); SYSERROR("Failed to exec %s", argv[0]); + lxc_write_error_message(fd, "Failed to exec: \"%s\": %s.", argv[0], strerror(errno)); free(argv); out1: diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index e99c41c..d641851 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -916,7 +916,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a NULL, }; char **init_cmd = NULL; - int keepfds[4] = {-1, -1, -1, -1}; + int keepfds[] = {-1, -1, -1, -1, -1}; + ssize_t size_read; + char errbuf[BUFSIZ + 1] = {0}; /* container does exist */ if (!c) @@ -962,7 +964,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a argv = init_cmd = split_init_cmd(conf->init_cmd); } - /* isulad: use init argv as init cmd */ + /* isulad: use init argv as init cmd */ if (!argv) { argv = init_cmd = use_init_args(conf->init_argv, conf->init_argc); } @@ -986,10 +988,19 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a char title[2048]; pid_t pid; + //isulad: pipdfd for get error message of child or grandchild process. + if (pipe2(conf->errpipe, O_CLOEXEC) != 0) { + SYSERROR("Failed to init errpipe"); + free_init_cmd(init_cmd); + lxc_free_handler(handler); + return false; + } + pid = fork(); if (pid < 0) { free_init_cmd(init_cmd); lxc_free_handler(handler); + lxc_close_error_pipe(conf->errpipe); return false; } @@ -999,11 +1010,23 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a * the PID file, child will do the free and unlink. */ c->pidfile = NULL; + close(conf->errpipe[1]); + conf->errpipe[1] = -1; /* Wait for container to tell us whether it started * successfully. */ started = wait_on_daemonized_start(handler, pid); + if (!started) { + size_read = read(conf->errpipe[0], errbuf, BUFSIZ); + if (size_read > 0) { + conf->errmsg = strdup(errbuf); + if (!conf->errmsg) + ERROR("Out of memory"); + } + } + close(conf->errpipe[0]); + conf->errpipe[0] = -1; free_init_cmd(init_cmd); lxc_free_handler(handler); @@ -1039,6 +1062,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a if (pid != 0) { free_init_cmd(init_cmd); lxc_free_handler(handler); + lxc_close_error_pipe(conf->errpipe); _exit(EXIT_SUCCESS); } @@ -1050,10 +1074,12 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a SYSERROR("Failed to change to \"/\" directory"); _exit(EXIT_FAILURE); } - + close(conf->errpipe[0]); + conf->errpipe[0] = -1; keepfds[0] = handler->conf->maincmd_fd; keepfds[1] = handler->state_socket_pair[0]; keepfds[2] = handler->state_socket_pair[1]; + keepfds[4] = conf->errpipe[1]; ret = lxc_check_inherited(conf, true, keepfds, sizeof(keepfds) / sizeof(keepfds[0])); if (ret < 0) @@ -1088,6 +1114,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a if (w < 0 || (size_t)w >= sizeof(pidstr)) { free_init_cmd(init_cmd); lxc_free_handler(handler); + lxc_close_error_pipe(conf->errpipe); SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile); @@ -1101,6 +1128,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a if (ret < 0) { free_init_cmd(init_cmd); lxc_free_handler(handler); + lxc_close_error_pipe(conf->errpipe); SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile); @@ -1159,6 +1187,9 @@ reboot: if (conf->exit_fd >= 0) { keepfds[3] = conf->exit_fd; } + /* isulad: keep errpipe fd */ + if (c->daemonize) + keepfds[4] = conf->errpipe[1]; ret = lxc_check_inherited(conf, c->daemonize, keepfds, sizeof(keepfds) / sizeof(keepfds[0])); if (ret < 0) { diff --git a/src/lxc/start.c b/src/lxc/start.c index ec61b32..3e6854f 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -892,6 +892,7 @@ int lxc_init(const char *name, struct lxc_handler *handler) ret = lxc_terminal_setup(conf); if (ret < 0) { ERROR("Failed to create console"); + lxc_write_error_message(conf->errpipe[1], "Failed to create console for container \"%s\".", name); goto out_restore_sigmask; } TRACE("Created console"); @@ -1390,6 +1391,8 @@ static int do_start(void *data) struct stat st; if (stat(handler->conf->init_cwd, &st) < 0 && mkdir_p(handler->conf->init_cwd, 0755) < 0) { SYSERROR("Try to create directory \"%s\" as workdir failed", handler->conf->init_cwd); + lxc_write_error_message(handler->conf->errpipe[1], "%s:%d: Failed to create workdir: %s.", + __FILE__, __LINE__, strerror(errno)); goto out_warn_father; } if (chdir(handler->conf->init_cwd)) { @@ -1489,7 +1492,7 @@ static int do_start(void *data) /* After this call, we are in error because this ops should not return * as it execs. */ - handler->ops->start(handler, handler->data); + handler->ops->start(handler, handler->data, handler->daemonize ? handler->conf->errpipe[1] : -1); out_warn_father: /* We want the parent to know something went wrong, so we return a @@ -1898,7 +1901,7 @@ static int lxc_spawn(struct lxc_handler *handler) goto out_delete_net; if (!lxc_list_empty(&conf->limits)) { - ret = setup_resource_limits(&conf->limits, handler->pid); + ret = setup_resource_limits(&conf->limits, handler->pid, conf->errpipe[1]); if (ret < 0) { ERROR("Failed to setup resource limits"); goto out_delete_net; @@ -1960,7 +1963,7 @@ static int lxc_spawn(struct lxc_handler *handler) } if (START_TIMEOUT == global_timeout_state) { - //lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); + lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); ERROR("Starting the container \"%s\" timeout.", name); goto out_delete_net; } @@ -2008,7 +2011,7 @@ static int lxc_spawn(struct lxc_handler *handler) } if (START_TIMEOUT == global_timeout_state) { - //lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); + lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name); ERROR("Starting the container \"%s\" timeout.", name); goto out_abort; } @@ -2232,7 +2235,7 @@ struct start_args { char *const *argv; }; -static int start(struct lxc_handler *handler, void* data) +static int start(struct lxc_handler *handler, void* data, int fd) { struct start_args *arg = data; @@ -2240,6 +2243,7 @@ static int start(struct lxc_handler *handler, void* data) execvp(arg->argv[0], arg->argv); SYSERROR("Failed to exec \"%s\"", arg->argv[0]); + lxc_write_error_message(fd, "exec: \"%s\": %s.", arg->argv[0], strerror(errno)); return 0; } diff --git a/src/lxc/start.h b/src/lxc/start.h index 1d84325..ab72e6e 100644 --- a/src/lxc/start.h +++ b/src/lxc/start.h @@ -145,7 +145,7 @@ struct execute_args { }; struct lxc_operations { - int (*start)(struct lxc_handler *, void *); + int (*start)(struct lxc_handler *, void *, int); int (*post_start)(struct lxc_handler *, void *); }; diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c index f37f8a6..ec48701 100644 --- a/src/lxc/tools/lxc_start.c +++ b/src/lxc/tools/lxc_start.c @@ -392,6 +392,9 @@ int main(int argc, char *argv[]) else err = c->start(c, 0, args) ? EXIT_SUCCESS : EXIT_FAILURE; if (err) { + if (c->lxc_conf->errmsg) + fprintf(stderr, "%s:%s:%s:%d starting container process caused \"%s\"", c->name, + __FILE__, __func__, __LINE__, c->lxc_conf->errmsg); ERROR("The container failed to start"); if (my_args.daemonize) -- 1.8.3.1