453 lines
12 KiB
Diff
453 lines
12 KiB
Diff
|
|
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
|
||
|
|
|