[CRIU] [PATCH 1/3] [v4] crtools: close a signal descriptor after passing a preparation stage

Andrei Vagin avagin at openvz.org
Tue Jan 10 13:21:43 PST 2017


From: Andrei Vagin <avagin at virtuozzo.com>

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

Cc: Mike Rapoport <mike.rapoport at gmail.com>
Cc: Kir Kolyshkin <kir at openvz.org>
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 Documentation/criu.txt    |  6 ++++++
 criu/crtools.c            | 10 ++++++++++
 criu/include/cr_options.h |  1 +
 criu/include/util.h       |  1 +
 criu/uffd.c               |  3 +++
 criu/util.c               | 18 ++++++++++++++++++
 6 files changed, 39 insertions(+)

diff --git a/Documentation/criu.txt b/Documentation/criu.txt
index b48572c..e8c7e73 100644
--- a/Documentation/criu.txt
+++ b/Documentation/criu.txt
@@ -522,6 +522,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 06b2fa7..445b3ba 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)
@@ -286,6 +287,7 @@ int main(int argc, char *argv[], char *envp[])
 		{ "check-only",			no_argument,		0, 1085 },
 		{ "display-stats",		no_argument,		0, 1086 },
 		{ "weak-sysctls",		no_argument,		0, 1087 },
+		{ "status-fd",			required_argument,	0, 1088 },
 		{ },
 	};
 
@@ -613,6 +615,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"))
@@ -951,6 +959,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 4f70b41..aaefea3 100644
--- a/criu/include/cr_options.h
+++ b/criu/include/cr_options.h
@@ -119,6 +119,7 @@ struct cr_options {
 	bool			display_stats;
 	bool			weak_sysctls;
 	bool			check_only;
+	int			status_fd;
 };
 
 extern struct cr_options opts;
diff --git a/criu/include/util.h b/criu/include/util.h
index 1fa0742..775d11e 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -171,6 +171,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/uffd.c b/criu/uffd.c
index ade5cbc..0f3b0f3 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -833,6 +833,9 @@ int cr_lazy_pages(bool daemon)
 		}
 	}
 
+	if (close_status_fd())
+		return -1;
+
 	nr_fds = task_entries->nr_tasks + (opts.use_page_server ? 1 : 0);
 	epollfd = epoll_prepare(nr_fds, &events);
 	if (epollfd < 0)
diff --git a/criu/util.c b/criu/util.c
index 2534a70..f917bc8 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)
-- 
2.7.4



More information about the CRIU mailing list