From 6affa9bf74fcc2ebb1dd785b73a47552669af82e Mon Sep 17 00:00:00 2001 From: tanyifeng Date: Wed, 3 Apr 2019 19:54:36 +0800 Subject: [PATCH 075/139] lxc: add timeout for attach Signed-off-by: wujing Signed-off-by: LiFeng --- src/lxc/attach.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/attach_options.h | 1 + src/lxc/tools/arguments.h | 4 +++ src/lxc/tools/lxc_attach.c | 11 +++++++ src/lxc/tools/lxc_start.c | 13 +------- src/lxc/utils.c | 13 ++++++++ src/lxc/utils.h | 2 ++ 7 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 618f2f1..79049c3 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -69,6 +69,20 @@ #include #endif +typedef enum { + ATTACH_INIT, + ATTACH_TIMEOUT, + ATTACH_MAX, +} attach_timeout_t; + +static volatile attach_timeout_t g_attach_timeout_state = ATTACH_INIT; + +struct attach_timeout_conf { + unsigned int timeout; + unsigned long long start_time; + pid_t pid; +}; + lxc_log_define(attach, lxc); /* Define default options if no options are supplied by the user. */ @@ -1145,6 +1159,59 @@ static inline void lxc_attach_terminal_close_log(struct lxc_terminal *terminal) terminal->log_fd = -EBADF; } +/* isulad: attach timeout thread function */ +static void* wait_attach_timeout(void *arg) +{ + struct attach_timeout_conf *conf = (struct attach_timeout_conf *)arg; + + if (!conf || conf->timeout < 1) + goto out; + sleep(conf->timeout); + if (lxc_process_alive(conf->pid, conf->start_time)) { + g_attach_timeout_state = ATTACH_TIMEOUT; + if (kill(conf->pid, SIGKILL) < 0) { + ERROR("Failed to send signal %d to pid %d", SIGKILL, conf->pid); + } + } + +out: + free(conf); + return ((void *)0); +} + +/* isulad: create attach timeout thread */ +static int create_attach_timeout_thread(unsigned int attach_timeout, pid_t pid) +{ + int ret = 0; + pthread_t ptid; + pthread_attr_t attr; + struct attach_timeout_conf *timeout_conf = NULL; + + timeout_conf = malloc(sizeof(struct attach_timeout_conf)); + if (!timeout_conf) { + ERROR("Failed to malloc attach timeout conf"); + ret = -1; + goto out; + } + + memset(timeout_conf, 0, sizeof(struct attach_timeout_conf)); + timeout_conf->timeout = attach_timeout; + timeout_conf->pid = pid; + timeout_conf->start_time = lxc_get_process_startat(pid); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&ptid, &attr, wait_attach_timeout, timeout_conf); + if (ret != 0) { + ERROR("Create attach wait timeout thread failed"); + free(timeout_conf); + goto out; + } + +out: + return ret; +} + 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, char **err_msg) @@ -1481,6 +1548,13 @@ int lxc_attach(const char *name, const char *lxcpath, *attached_process = attached_pid; + if (options->timeout > 0) { + ret = create_attach_timeout_thread(options->timeout, *attached_process); + if (ret) { + ERROR("Failed to create attach timeout thread for container."); + goto close_mainloop; + } + } /* isulad: read error msg from pipe */ ssize_t size_read; char errbuf[BUFSIZ + 1] = {0}; @@ -1510,6 +1584,11 @@ int lxc_attach(const char *name, const char *lxcpath, } } + if (g_attach_timeout_state == ATTACH_TIMEOUT && err_msg != NULL && *err_msg == NULL) { + *err_msg = strdup("Attach exceeded timeout"); + if (!(*err_msg)) + ERROR("Out of memory"); + } close_mainloop: if (options->attach_flags & LXC_ATTACH_TERMINAL) lxc_mainloop_close(&descr); diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h index 71c1739..5e279ba 100644 --- a/src/lxc/attach_options.h +++ b/src/lxc/attach_options.h @@ -137,6 +137,7 @@ typedef struct lxc_attach_options_t { int log_fd; char *init_fifo[3]; /* isulad: default fifos for the start */ + unsigned int timeout;/* isulad: Seconds for waiting on a container to attach/exec before it is killed*/ } lxc_attach_options_t; /*! Default attach options to use */ diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h index d03f8a4..2fc90ad 100644 --- a/src/lxc/tools/arguments.h +++ b/src/lxc/tools/arguments.h @@ -69,6 +69,9 @@ struct lxc_arguments { const char *exit_monitor_fifo; /* isulad: fifo used to monitor state of monitor process */ unsigned int start_timeout; /* isulad: Seconds for waiting on a container to start before it is killed*/ + /* for lxc-attach */ + unsigned int attach_timeout; + /* for lxc-console */ unsigned int ttynum; char escape; @@ -187,6 +190,7 @@ struct lxc_arguments { #define OPT_START_TIMEOUT OPT_USAGE - 12 #define OPT_DISABLE_PTY OPT_USAGE - 13 #define OPT_OPEN_STDIN OPT_USAGE - 14 +#define OPT_ATTACH_TIMEOUT OPT_USAGE - 15 /* isulad add end*/ diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c index 674050d..2861ef4 100644 --- a/src/lxc/tools/lxc_attach.c +++ b/src/lxc/tools/lxc_attach.c @@ -62,6 +62,7 @@ static char **extra_env; static ssize_t extra_env_size; static char **extra_keep; static ssize_t extra_keep_size; +static unsigned int timeout = 0; static const struct option my_longopts[] = { {"elevated-privileges", optional_argument, 0, 'e'}, @@ -78,6 +79,7 @@ static const struct option my_longopts[] = { {"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}, + {"timeout", required_argument, 0, OPT_ATTACH_TIMEOUT}, LXC_COMMON_OPTIONS }; @@ -128,6 +130,7 @@ Options :\n\ multiple times.\n\ -f, --rcfile=FILE\n\ Load configuration file FILE\n\ + --timeout Timeout in seconds (default: 0)\n\ ", .options = my_longopts, .parser = my_parser, @@ -205,6 +208,13 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg) case OPT_STDERR_FIFO: args->terminal_fifos[2] = arg; break; + case OPT_ATTACH_TIMEOUT: + if(!is_non_negative_num(arg)) { + ERROR("Error attach timeout parameter:%s.\n", arg); + return -1; + } + args->attach_timeout = (unsigned int)atoi(arg); + break; } return 0; @@ -478,6 +488,7 @@ int main(int argc, char *argv[]) attach_options.env_policy = env_policy; attach_options.extra_env_vars = extra_env; attach_options.extra_keep_env = extra_keep; + attach_options.timeout = my_args.attach_timeout; if (my_args.argc > 0) { command.program = my_args.argv[0]; diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c index 183fafc..af63f58 100644 --- a/src/lxc/tools/lxc_start.c +++ b/src/lxc/tools/lxc_start.c @@ -49,6 +49,7 @@ #include "config.h" #include "confile.h" #include "log.h" +#include "utils.h" lxc_log_define(lxc_start, lxc); @@ -113,18 +114,6 @@ Options :\n\ .pidfile = NULL, }; -static bool is_non_negative_num(const char *s) -{ - if (!s || !strcmp(s, "")) - return false; - while(*s != '\0') { - if(!isdigit(*s)) - return false; - ++s; - } - return true; -} - static int my_parser(struct lxc_arguments *args, int c, char *arg) { switch (c) { diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 480e6d0..69eb3e5 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -2069,3 +2069,16 @@ out: free(pid_info); return alive; } + +bool is_non_negative_num(const char *s) +{ + if (!s || !strcmp(s, "")) + return false; + while(*s != '\0') { + if(!isdigit(*s)) + return false; + ++s; + } + return true; +} + diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 73ffdd9..20407af 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -322,4 +322,6 @@ extern void lxc_write_error_message(int errfd, const char *format, ...); extern bool lxc_process_alive(pid_t pid, unsigned long long start_time); +extern bool is_non_negative_num(const char *s); + #endif /* __LXC_UTILS_H */ -- 1.8.3.1