From 204008167f00ddda3f5f2b0121bcf29b3d55c689 Mon Sep 17 00:00:00 2001 From: LiFeng Date: Mon, 13 Apr 2020 21:17:15 +0800 Subject: [PATCH 16/49] start: separate -i and -t Signed-off-by: LiFeng --- src/lxc/lxccontainer.c | 44 +++++++++++++++++- src/lxc/lxccontainer.h | 27 +++++++++++ src/lxc/start.c | 111 +++++++++++++++++++++++++++++++++++++++++++++- src/lxc/start.h | 4 ++ src/lxc/tools/arguments.h | 2 + src/lxc/tools/lxc_start.c | 14 ++++++ 6 files changed, 198 insertions(+), 4 deletions(-) diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 64cde99..e27b63b 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -1163,12 +1163,18 @@ reboot: goto on_error; } - if (useinit) + if (useinit) { ret = lxc_execute(c->name, argv, 1, handler, c->config_path, c->daemonize, &c->error_num); - else + } + else { +#ifdef HAVE_ISULAD + handler->disable_pty = c->disable_pty; + handler->open_stdin = c->open_stdin; +#endif ret = lxc_start(argv, handler, c->config_path, c->daemonize, &c->error_num); + } if (conf->reboot == REBOOT_REQ) { INFO("Container requested reboot"); @@ -5381,6 +5387,40 @@ static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const cha } WRAP_API_1(bool, lxcapi_set_container_info_file, const char *) + +static bool do_lxcapi_want_disable_pty(struct lxc_container *c, bool state) +{ + if (!c || !c->lxc_conf) + return false; + + if (container_mem_lock(c)) + return false; + + c->disable_pty = state; + + container_mem_unlock(c); + + return true; +} + +WRAP_API_1(bool, lxcapi_want_disable_pty, bool) + +static bool do_lxcapi_want_open_stdin(struct lxc_container *c, bool state) +{ + if (!c || !c->lxc_conf) + return false; + + if (container_mem_lock(c)) + return false; + + c->open_stdin = state; + + container_mem_unlock(c); + + return true; +} + +WRAP_API_1(bool, lxcapi_want_open_stdin, bool) #endif struct lxc_container *lxc_container_new(const char *name, const char *configpath) diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h index fa9bd5e..de2ee46 100644 --- a/src/lxc/lxccontainer.h +++ b/src/lxc/lxccontainer.h @@ -113,6 +113,11 @@ struct lxc_container { * exit FIFO File to open used monitor the state of lxc monitor process. */ char *exit_fifo; + /*! Whether container wishes to create pty or pipes for console log */ + bool disable_pty; + + /*! Whether container wishes to keep stdin active */ + bool open_stdin; #endif /*! @@ -908,6 +913,28 @@ struct lxc_container { bool (*set_terminal_winch)(struct lxc_container *c, unsigned int height, unsigned int width); bool (*set_exec_terminal_winch)(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width); + + /*! + * \brief Change whether the container wants to create pty or pipes + * from the console log. + * + * \param c Container. + * \param state Value for the disable pty bit (0 or 1). + * + * \return \c true on success, else \c false. + */ + bool (*want_disable_pty)(struct lxc_container *c, bool state); + + /*! + * \brief Change whether the container wants to keep stdin active + * for parent process of container + * + * \param c Container. + * \param state Value for the open_stdin bit (0 or 1). + * + * \return \c true on success, else \c false. + */ + bool (*want_open_stdin)(struct lxc_container *c, bool state); #endif }; diff --git a/src/lxc/start.c b/src/lxc/start.c index 17766bc..145b015 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -580,6 +580,16 @@ int lxc_poll(const char *name, struct lxc_handler *handler) TRACE("Mainloop is ready"); +#ifdef HAVE_ISULAD + // iSulad: close stdin pipe if we do not want open_stdin with container stdin + if (!handler->conf->console.open_stdin) { + if (handler->conf->console.pipes[0][1] > 0) { + close(handler->conf->console.pipes[0][1]); + handler->conf->console.pipes[0][1] = -1; + } + } +#endif + ret = lxc_mainloop(&descr, -1); close_prot_errno_disarm(descr.epfd); if (ret < 0 || !handler->init_died) @@ -733,6 +743,10 @@ int lxc_init(const char *name, struct lxc_handler *handler) int ret; const char *loglevel; struct lxc_conf *conf = handler->conf; +#ifdef HAVE_ISULAD + conf->console.disable_pty = handler->disable_pty; + conf->console.open_stdin = handler->open_stdin; +#endif handler->monitor_pid = lxc_raw_getpid(); status_fd = open("/proc/self/status", O_RDONLY | O_CLOEXEC); @@ -1178,6 +1192,25 @@ static int do_start(void *data) * means that migration won't work, but at least we won't spew output * where it isn't wanted. */ +#ifdef HAVE_ISULAD + if (!handler->disable_pty && handler->daemonize && !handler->conf->autodev) { + char path[PATH_MAX]; + + ret = snprintf(path, sizeof(path), "%s/dev/null", + handler->conf->rootfs.mount); + if (ret < 0 || ret >= sizeof(path)) + goto out_warn_father; + + ret = access(path, F_OK); + if (ret != 0) { + devnull_fd = open_devnull(); + + if (devnull_fd < 0) + goto out_warn_father; + WARN("Using /dev/null from the host for container init's standard file descriptors. Migration will not work"); + } + } +#else if (handler->daemonize && !handler->conf->autodev) { char path[PATH_MAX]; @@ -1195,6 +1228,7 @@ static int do_start(void *data) WARN("Using /dev/null from the host for container init's standard file descriptors. Migration will not work"); } } +#endif /* Ask father to setup cgroups and wait for him to finish. */ ret = lxc_sync_barrier_parent(handler, LXC_SYNC_CGROUP); @@ -1266,12 +1300,70 @@ static int do_start(void *data) DEBUG("Set PR_SET_NO_NEW_PRIVS to block execve() gainable privileges"); } +#ifdef HAVE_ISULAD + /* isulad: dup2 pipe[0][0] to container stdin, pipe[1][1] to container stdout, pipe[2][1] to container stderr */ + if (handler->disable_pty) { + if (handler->conf->console.pipes[0][1] >= 0) { + close(handler->conf->console.pipes[0][1]); + handler->conf->console.pipes[0][1] = -1; + } + + if (handler->conf->console.pipes[0][0] >= 0) { + ret = dup2(handler->conf->console.pipes[0][0], STDIN_FILENO); + if (ret < 0) + goto out_warn_father; + } + + if (handler->conf->console.pipes[1][0] >= 0) { + close(handler->conf->console.pipes[1][0]); + handler->conf->console.pipes[1][0] = -1; + } + + if (handler->conf->console.pipes[1][1] >= 0) { + ret = dup2(handler->conf->console.pipes[1][1], STDOUT_FILENO); + if (ret < 0) + goto out_warn_father; + } + if (handler->conf->console.pipes[2][0] >= 0) { + close(handler->conf->console.pipes[2][0]); + handler->conf->console.pipes[2][0] = -1; + } + + if (handler->conf->console.pipes[2][1] >= 0) { + ret = dup2(handler->conf->console.pipes[2][1], STDERR_FILENO); + if (ret < 0) + goto out_warn_father; + } + } +#endif + /* Some init's such as busybox will set sane tty settings on stdin, * stdout, stderr which it thinks is the console. We already set them * the way we wanted on the real terminal, and we want init to do its * setup on its console ie. the pty allocated in lxc_terminal_setup() so * make sure that that pty is stdin,stdout,stderr. */ + setsid(); +#ifdef HAVE_ISULAD + if (!handler->disable_pty && handler->conf->console.slave >= 0) { + /* isulad:make the given terminal as controlling terminal to avoid warning + * sh: cannot set terminal process group (-1): Inappropriate ioctl for device + * sh: no job control in this shell */ + if (ioctl(handler->conf->console.slave, TIOCSCTTY, NULL) < 0) { + ERROR("Faild to make the given terminal the controlling terminal of the calling process"); + goto out_warn_father; + } + if (handler->daemonize || !handler->conf->is_execute) + ret = set_stdfds(handler->conf->console.slave); + else + ret = lxc_terminal_set_stdfds(handler->conf->console.slave); + if (ret < 0) { + ERROR("Failed to redirect std{in,out,err} to pty file " + "descriptor %d", handler->conf->console.slave); + goto out_warn_father; + } + } +#else if (handler->conf->console.slave >= 0) { if (handler->daemonize || !handler->conf->is_execute) ret = set_stdfds(handler->conf->console.slave); @@ -1283,6 +1375,7 @@ static int do_start(void *data) goto out_warn_father; } } +#endif /* If we mounted a temporary proc, then unmount it now. */ tmp_proc_unmount(handler->conf); @@ -1306,6 +1399,21 @@ static int do_start(void *data) close_prot_errno_disarm(handler->sigfd); + #ifdef HAVE_ISULAD + if (!handler->disable_pty && handler->conf->console.slave < 0 && handler->daemonize) { + if (devnull_fd < 0) { + devnull_fd = open_devnull(); + if (devnull_fd < 0) + goto out_warn_father; + } + + ret = set_stdfds(devnull_fd); + if (ret < 0) { + ERROR("Failed to redirect std{in,out,err} to \"/dev/null\""); + goto out_warn_father; + } + } + #else if (handler->conf->console.slave < 0 && handler->daemonize) { if (devnull_fd < 0) { devnull_fd = open_devnull(); @@ -1319,11 +1427,10 @@ static int do_start(void *data) goto out_warn_father; } } + #endif close_prot_errno_disarm(devnull_fd); - setsid(); - if (handler->conf->init_cwd) { ret = chdir(handler->conf->init_cwd); if (ret < 0) { diff --git a/src/lxc/start.h b/src/lxc/start.h index 1368d0e..5ea5fe2 100644 --- a/src/lxc/start.h +++ b/src/lxc/start.h @@ -125,6 +125,10 @@ struct lxc_handler { #ifdef HAVE_ISULAD int exit_code;/* isulad: record the exit code of container */ + /* Indicates whether should we using pipes or pty dup to std{in,out,err} for console log. */ + bool disable_pty; + /* Indicates whether should we keep stdin active. */ + bool open_stdin; #endif }; diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h index e0866d6..a6d9967 100644 --- a/src/lxc/tools/arguments.h +++ b/src/lxc/tools/arguments.h @@ -45,6 +45,8 @@ struct lxc_arguments { char *terminal_fifos[3]; /* isulad add, fifos used to redirct stdin/out/err */ const char *exit_monitor_fifo; /* isulad: fifo used to monitor state of monitor process */ const char *suffix; /* isulad add, suffix used for connect with parent of execed process*/ + int disable_pty; + int open_stdin; #endif /* for lxc-console */ diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c index 76802df6..321c847 100644 --- a/src/lxc/tools/lxc_start.c +++ b/src/lxc/tools/lxc_start.c @@ -143,6 +143,12 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) case OPT_EXIT_FIFO: args->exit_monitor_fifo = arg; break; + case OPT_DISABLE_PTY: + args->disable_pty = 1; + break; + case OPT_OPEN_STDIN: + args->open_stdin = 1; + break; #endif } @@ -334,6 +340,14 @@ int main(int argc, char *argv[]) if (my_args.exit_monitor_fifo != NULL) { c->exit_fifo = safe_strdup(my_args.exit_monitor_fifo); } + + if (my_args.disable_pty) { + c->want_disable_pty(c, true); + } + + if (my_args.open_stdin) { + c->want_open_stdin(c, true); + } #endif if (my_args.console) -- 1.8.3.1