lxc/0014-exec-refact-attach-progress.patch

453 lines
12 KiB
Diff
Raw Normal View History

From 61b64be9ac4e5d46e9363bb605c7b2e14d0cd2a2 Mon Sep 17 00:00:00 2001
From: LiFeng <lifeng68@huawei.com>
Date: Mon, 13 Apr 2020 20:41:03 +0800
Subject: [PATCH 14/49] exec: refact attach progress
Signed-off-by: LiFeng <lifeng68@huawei.com>
---
src/lxc/attach.c | 2 +-
src/lxc/attach_options.h | 23 +++-
src/lxc/conf.h | 2 +
src/lxc/terminal.c | 27 ++++-
src/lxc/tools/arguments.h | 1 +
src/lxc/tools/lxc_attach.c | 273 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 324 insertions(+), 4 deletions(-)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 801dc27..e66ca1c 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -1420,7 +1420,7 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
}
if (pid == 0) {
- if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ if (options->attach_flags & LXC_ATTACH_TERMINAL && terminal.tty_state) {
ret = pthread_sigmask(SIG_SETMASK,
&terminal.tty_state->oldmask, NULL);
if (ret < 0) {
diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h
index 3a02ee5..7b0ea5e 100644
--- a/src/lxc/attach_options.h
+++ b/src/lxc/attach_options.h
@@ -116,10 +116,12 @@ typedef struct lxc_attach_options_t {
#ifdef HAVE_ISULAD
char *init_fifo[3]; /* isulad: default fifos for the start */
int64_t timeout;/* isulad: Seconds for waiting on a container to attach/exec before it is killed*/
+ const char *suffix;
#endif
} lxc_attach_options_t;
+#ifdef HAVE_ISULAD
/*! Default attach options to use */
#define LXC_ATTACH_OPTIONS_DEFAULT \
{ \
@@ -136,8 +138,27 @@ typedef struct lxc_attach_options_t {
/* .stdout_fd = */ 1, \
/* .stderr_fd = */ 2, \
/* .log_fd = */ -EBADF, \
+ /* .init_fifo = */ {NULL, NULL, NULL}, \
}
-
+#else
+/*! Default attach options to use */
+#define LXC_ATTACH_OPTIONS_DEFAULT \
+ { \
+ /* .attach_flags = */ LXC_ATTACH_DEFAULT, \
+ /* .namespaces = */ -1, \
+ /* .personality = */ -1, \
+ /* .initial_cwd = */ NULL, \
+ /* .uid = */ (uid_t)-1, \
+ /* .gid = */ (gid_t)-1, \
+ /* .env_policy = */ LXC_ATTACH_KEEP_ENV, \
+ /* .extra_env_vars = */ NULL, \
+ /* .extra_keep_env = */ NULL, \
+ /* .stdin_fd = */ 0, \
+ /* .stdout_fd = */ 1, \
+ /* .stderr_fd = */ 2, \
+ /* .log_fd = */ -EBADF, \
+ }
+#endif
/*!
* Representation of a command to run in a container.
*/
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index c5b70e1..52460a3 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -432,6 +432,8 @@ struct lxc_conf {
char *container_info_file;
int exit_fd; /* exit fifo fd*/
+
+ char *errmsg; /* record error messages */
#endif
};
diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c
index c8cd83f..775743d 100644
--- a/src/lxc/terminal.c
+++ b/src/lxc/terminal.c
@@ -1174,8 +1174,25 @@ static int lxc_terminal_peer_default(struct lxc_terminal *terminal)
if (terminal->path)
path = terminal->path;
- else
- path = "/dev/tty";
+
+#ifdef HAVE_ISULAD
+ /* isulad: if no console was given, try current controlling terminal, there
+ * won't be one if we were started as a daemon (-d)
+ */
+ if (!path && !access("/dev/tty", F_OK)) {
+ int fd;
+ fd = open("/dev/tty", O_RDWR);
+ if (fd >= 0) {
+ close(fd);
+ path = "/dev/tty";
+ }
+ }
+
+ if (!path) {
+ DEBUG("Not have a controlling terminal");
+ return 0;
+ }
+#endif
terminal->peer = lxc_unpriv(open(path, O_RDWR | O_CLOEXEC));
if (terminal->peer < 0) {
@@ -1884,9 +1901,15 @@ int lxc_terminal_prepare_login(int fd)
if (ret < 0)
return -1;
+#ifdef HAVE_ISULAD
+ ret = set_stdfds(fd);
+ if (ret < 0)
+ return -1;
+#else
ret = lxc_terminal_set_stdfds(fd);
if (ret < 0)
return -1;
+#endif
if (fd > STDERR_FILENO)
close(fd);
diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h
index ea5f938..e0866d6 100644
--- a/src/lxc/tools/arguments.h
+++ b/src/lxc/tools/arguments.h
@@ -44,6 +44,7 @@ struct lxc_arguments {
const char *container_info; /* isulad: file used to store pid and ppid info of container */
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*/
#endif
/* for lxc-console */
diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index a8f493a..47ac2f2 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -74,6 +74,12 @@ static const struct option my_longopts[] = {
{"rcfile", required_argument, 0, 'f'},
{"uid", required_argument, 0, 'u'},
{"gid", required_argument, 0, 'g'},
+#ifdef HAVE_ISULAD
+ {"in-fifo", required_argument, 0, OPT_INPUT_FIFO}, /* isulad add terminal fifos*/
+ {"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO},
+ {"err-fifo", required_argument, 0, OPT_STDERR_FIFO},
+ {"suffix", required_argument, 0, OPT_ATTACH_SUFFIX},
+#endif
LXC_COMMON_OPTIONS
};
@@ -201,6 +207,20 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
if (lxc_safe_uint(arg, &args->gid) < 0)
return -1;
break;
+#ifdef HAVE_ISULAD
+ case OPT_INPUT_FIFO:
+ args->terminal_fifos[0] = arg;
+ break;
+ case OPT_OUTPUT_FIFO:
+ args->terminal_fifos[1] = arg;
+ break;
+ case OPT_STDERR_FIFO:
+ args->terminal_fifos[2] = arg;
+ break;
+ case OPT_ATTACH_SUFFIX:
+ args->suffix = arg;
+ break;
+#endif
}
return 0;
@@ -264,6 +284,258 @@ static int lxc_attach_create_log_file(const char *log_file)
return fd;
}
+#ifdef HAVE_ISULAD
+// isulad: send '128 + signal' if container is killed by signal.
+#define ExitSignalOffset 128
+
+/*isulad: attach with terminal*/
+static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *command,
+ lxc_attach_options_t *attach_options,
+ char **errmsg)
+{
+ int ret = 0;
+ pid_t pid;
+ int wexit = -1;
+ int signal;
+
+ if (command->program)
+ ret = c->attach(c, lxc_attach_run_command, command, attach_options, &pid);
+ else
+ ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid);
+ if (ret < 0)
+ goto out;
+
+ ret = lxc_wait_for_pid_status(pid);
+ if (ret < 0)
+ goto out;
+
+ if (WIFEXITED(ret))
+ wexit = WEXITSTATUS(ret);
+ else
+ wexit = -1;
+
+ if (WIFSIGNALED(ret)) {
+ signal = WTERMSIG(ret);
+ wexit = ExitSignalOffset + signal;
+ }
+out:
+ if (c->lxc_conf->errmsg)
+ *errmsg = safe_strdup(c->lxc_conf->errmsg);
+ return wexit;
+}
+
+static void close_msg_pipe(int *errpipe)
+{
+ if (errpipe[0] >= 0) {
+ close(errpipe[0]);
+ errpipe[0] = -1;
+ }
+ if (errpipe[1] >= 0) {
+ close(errpipe[1]);
+ errpipe[1] = -1;
+ }
+}
+
+/*isulad: attach without terminal in background */
+static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *command,
+ lxc_attach_options_t *attach_options,
+ char **errmsg)
+{
+ int ret = 0;
+ int msgpipe[2];
+ pid_t pid = 0;
+ ssize_t size_read;
+ char msgbuf[BUFSIZ + 1] = {0};
+
+ //pipdfd for get error message of child or grandchild process.
+ if (pipe2(msgpipe, O_CLOEXEC) != 0) {
+ SYSERROR("Failed to init msgpipe");
+ return -1;
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ close_msg_pipe(msgpipe);
+ return -1;
+ }
+
+ if (pid != 0) {
+ close(msgpipe[1]);
+ msgpipe[1] = -1;
+ size_read = read(msgpipe[0], msgbuf, BUFSIZ);
+ if (size_read > 0) {
+ *errmsg = safe_strdup(msgbuf);
+ ret = -1;
+ }
+
+ close(msgpipe[0]);
+ msgpipe[0] = -1;
+
+ return ret;
+ }
+
+ /* second fork to be reparented by init */
+ pid = fork();
+ if (pid < 0) {
+ SYSERROR("Error doing dual-fork");
+ close_msg_pipe(msgpipe);
+ exit(1);
+ }
+ if (pid != 0) {
+ close_msg_pipe(msgpipe);
+ exit(0);
+ }
+
+ close(msgpipe[0]);
+ msgpipe[0] = -1;
+
+ if (null_stdfds() < 0) {
+ ERROR("failed to close fds");
+ exit(1);
+ }
+ setsid();
+
+ if (command->program)
+ ret = c->attach(c, lxc_attach_run_command, command, attach_options, &pid);
+ 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);
+ else
+ lxc_write_error_message(msgpipe[1], "Failed to attach container");
+ close(msgpipe[1]);
+ msgpipe[1] = -1;
+ ret = -1;
+ goto out;
+ }
+
+ close(msgpipe[1]);
+ msgpipe[1] = -1;
+
+ ret = wait_for_pid(pid);
+out:
+ lxc_container_put(c);
+ if (ret)
+ exit(EXIT_FAILURE);
+ else
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = -1;
+ int wexit = 0;
+ struct lxc_log log;
+ char *errmsg = NULL;
+ pid_t pid;
+ lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
+ lxc_attach_command_t command = (lxc_attach_command_t){.program = NULL};
+
+ if (lxc_caps_init())
+ exit(EXIT_FAILURE);
+
+ if (lxc_arguments_parse(&my_args, argc, argv))
+ exit(EXIT_FAILURE);
+
+ log.name = my_args.name;
+ log.file = my_args.log_file;
+ log.level = my_args.log_priority;
+ log.prefix = my_args.progname;
+ log.quiet = my_args.quiet;
+ log.lxcpath = my_args.lxcpath[0];
+
+ if (lxc_log_init(&log))
+ exit(EXIT_FAILURE);
+
+ if (geteuid())
+ if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
+ ERROR("You lack access to %s", my_args.lxcpath[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ struct lxc_container *c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
+ if (!c)
+ exit(EXIT_FAILURE);
+
+ if (my_args.rcfile) {
+ c->clear_config(c);
+ if (!c->load_config(c, my_args.rcfile)) {
+ ERROR("Failed to load rcfile");
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+
+ c->configfile = strdup(my_args.rcfile);
+ if (!c->configfile) {
+ ERROR("Out of memory setting new config filename");
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!c->may_control(c)) {
+ ERROR("Insufficent privileges to control %s", c->name);
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+
+ if (remount_sys_proc)
+ attach_options.attach_flags |= LXC_ATTACH_REMOUNT_PROC_SYS;
+
+ if (elevated_privileges)
+ attach_options.attach_flags &= ~(elevated_privileges);
+
+ if (my_args.terminal_fifos[0] || my_args.terminal_fifos[1] || my_args.terminal_fifos[2]) {
+ attach_options.init_fifo[0] = my_args.terminal_fifos[0];
+ attach_options.init_fifo[1] = my_args.terminal_fifos[1];
+ attach_options.init_fifo[2] = my_args.terminal_fifos[2];
+ attach_options.attach_flags |= LXC_ATTACH_TERMINAL;
+ } else if (stdfd_is_pty()) {
+ attach_options.attach_flags |= LXC_ATTACH_TERMINAL;
+ }
+
+ attach_options.namespaces = namespace_flags;
+ attach_options.personality = new_personality;
+ attach_options.env_policy = env_policy;
+ attach_options.extra_env_vars = extra_env;
+ attach_options.extra_keep_env = extra_keep;
+
+ if (my_args.argc > 0) {
+ command.program = my_args.argv[0];
+ command.argv = (char**)my_args.argv;
+ }
+
+ if (my_args.console_log) {
+ attach_options.log_fd = lxc_attach_create_log_file(my_args.console_log);
+ if (attach_options.log_fd < 0) {
+ ERROR("Failed to create log file for %s", c->name);
+ lxc_container_put(c);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ attach_options.suffix = my_args.suffix;
+
+ /* isulad: add do attach background */
+ if (attach_options.attach_flags & LXC_ATTACH_TERMINAL)
+ wexit = do_attach_foreground(c, &command, &attach_options, &errmsg);
+ else
+ wexit = do_attach_background(c, &command, &attach_options, &errmsg);
+
+ if (errmsg) {
+ fprintf(stderr, "%s:%s:%s:%d starting container process caused \"%s\"", c->name,
+ __FILE__, __func__, __LINE__, errmsg);
+ free(errmsg);
+ }
+
+ lxc_container_put(c);
+ if (wexit >= 0)
+ exit(wexit);
+
+ exit(EXIT_FAILURE);
+}
+#else
int main(int argc, char *argv[])
{
int ret = -1;
@@ -377,3 +649,4 @@ out:
exit(EXIT_FAILURE);
}
+#endif
--
1.8.3.1