From ac5cac188d6c81bf9314efce364d3573d40e4b5e Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Tue, 24 Jan 2017 01:57:41 +0300 Subject: [PATCH] crtools: close a signal descriptor after passing a preparation stage This patch adds the --siganl-fd FD option to specify a file descriptor. CRIU will write '\0' to this descriptor and close it after passing a preparation stage. It is alternative way to demonizing a criu process after a preparation stage. It's imposiable to get exit code, if a process has daemonized. The introduced way allows to wait a preparation stage and to get an exit code. It can be easy used from shell and other script languages. v3: fix a help message v4: Here is a sequence of actions how it can be used: * open a pipe * run a service with the pipe[1] as status_fd * read(pipe[0]) to wait a moment when the service will be ready to accept connections * do a work which requires the service * wait the service process to gets its exit status to be sure that everything okey travis-ci: success for crtools: close a signal descriptor after passing a preparation stage (rev6) Cc: Mike Rapoport Cc: Kir Kolyshkin Signed-off-by: Andrei Vagin Signed-off-by: Pavel Emelyanov --- Documentation/criu.txt | 6 ++++++ criu/crtools.c | 10 ++++++++++ criu/include/cr_options.h | 1 + criu/include/util.h | 1 + criu/util.c | 18 ++++++++++++++++++ 5 files changed, 36 insertions(+) diff --git a/Documentation/criu.txt b/Documentation/criu.txt index 4a451865e..57cecfb20 100644 --- a/Documentation/criu.txt +++ b/Documentation/criu.txt @@ -506,6 +506,12 @@ Launches *criu* in page server mode. *--daemon*:: Runs page server as a daemon (background process). +*--status_fd*:: + Write \\0 to the FD and close it once page-server is ready to handle + requests. The status-fd allows to not daemonize a process and get its + exit code at the end. + It isn't supposed to use --daemon and --status-fd together. + *--address* 'address':: Page server IP address. diff --git a/criu/crtools.c b/criu/crtools.c index d5a544709..b8c01232e 100644 --- a/criu/crtools.c +++ b/criu/crtools.c @@ -76,6 +76,7 @@ void init_opts(void) opts.ghost_limit = DEFAULT_GHOST_LIMIT; opts.timeout = DEFAULT_TIMEOUT; opts.empty_ns = 0; + opts.status_fd = -1; } static int parse_join_ns(const char *ptr) @@ -285,6 +286,7 @@ int main(int argc, char *argv[], char *envp[]) { "deprecated", no_argument, 0, 1084 }, { "display-stats", no_argument, 0, 1086 }, { "weak-sysctls", no_argument, 0, 1087 }, + { "status-fd", required_argument, 0, 1088 }, { }, }; @@ -604,6 +606,12 @@ int main(int argc, char *argv[], char *envp[]) pr_msg("Will skip non-existant sysctls on restore\n"); opts.weak_sysctls = true; break; + case 1088: + if (sscanf(optarg, "%d", &opts.status_fd) != 1) { + pr_err("Unable to parse a value of --status-fd\n"); + return 1; + } + break; case 'V': pr_msg("Version: %s\n", CRIU_VERSION); if (strcmp(CRIU_GITID, "0")) @@ -940,6 +948,8 @@ usage: " --address ADDR address of server or service\n" " --port PORT port of page server\n" " -d|--daemon run in the background after creating socket\n" +" --status-fd FD write \\0 to the FD and close it once process is ready\n" +" to handle requests\n" "\n" "Other options:\n" " -h|--help show this text\n" diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h index c2f4b1083..1aec65707 100644 --- a/criu/include/cr_options.h +++ b/criu/include/cr_options.h @@ -117,6 +117,7 @@ struct cr_options { bool deprecated_ok; bool display_stats; bool weak_sysctls; + int status_fd; }; extern struct cr_options opts; diff --git a/criu/include/util.h b/criu/include/util.h index ea0e4b6ae..57e36ed3e 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -172,6 +172,7 @@ extern int cr_system(int in, int out, int err, char *cmd, char *const argv[], un extern int cr_system_userns(int in, int out, int err, char *cmd, char *const argv[], unsigned flags, int userns_pid); extern int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd); +extern int close_status_fd(void); extern int is_root_user(void); static inline bool dir_dots(const struct dirent *de) diff --git a/criu/util.c b/criu/util.c index d584edefa..437796b2b 100644 --- a/criu/util.c +++ b/criu/util.c @@ -690,6 +690,21 @@ out: return ret; } +int close_status_fd(void) +{ + char c = 0; + + if (opts.status_fd < 0) + return 0; + + if (write(opts.status_fd, &c, 1) != 1) { + pr_perror("Unable to write into the status fd"); + return -1; + } + + return close_safe(&opts.status_fd); +} + int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd) { int pid; @@ -1155,6 +1170,9 @@ int run_tcp_server(bool daemon_mode, int *ask, int cfd, int sk) } } + if (close_status_fd()) + return -1; + if (sk >= 0) { ret = *ask = accept(sk, (struct sockaddr *)&caddr, &clen); if (*ask < 0)