crtools: close a signal descriptor after passing a preparation stage

Submitted by Andrei Vagin on Nov. 16, 2016, 10:03 p.m.

Details

Message ID 1479333788-16852-1-git-send-email-avagin@openvz.org
State Superseded
Series "crtools: close a signal descriptor after passing a preparation stage"
Headers show

Commit Message

Andrei Vagin Nov. 16, 2016, 10:03 p.m.
From: Andrei Vagin <avagin@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.

Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
---
 criu/crtools.c            | 13 ++++++++++++-
 criu/include/cr_options.h |  1 +
 criu/include/util.h       |  1 +
 criu/uffd.c               |  3 +++
 criu/util.c               | 18 ++++++++++++++++++
 5 files changed, 35 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/criu/crtools.c b/criu/crtools.c
index 710059f..6c468f6 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -55,7 +55,9 @@ 
 
 #include "../soccr/soccr.h"
 
-struct cr_options opts;
+struct cr_options opts = {
+	.status_fd = -1,
+};
 
 void init_opts(void)
 {
@@ -285,6 +287,7 @@  int main(int argc, char *argv[], char *envp[])
 		{ "deprecated",			no_argument,		0, 1084 },
 		{ "check-only",			no_argument,		0, 1085 },
 		{ "display-stats",		no_argument,		0, 1086 },
+		{ "status-fd",			required_argument,	0, 1087 },
 		{ },
 	};
 
@@ -608,6 +611,12 @@  int main(int argc, char *argv[], char *envp[])
 		case 1086:
 			opts.display_stats = true;
 			break;
+		case 1087:
+			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"))
@@ -945,6 +954,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' and close FD after passing a preparation\n"
+"                        stage\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 e017236..abebe05 100644
--- a/criu/include/cr_options.h
+++ b/criu/include/cr_options.h
@@ -118,6 +118,7 @@  struct cr_options {
 	bool			deprecated_ok;
 	bool			display_stats;
 	bool			check_only;
+	int			status_fd;
 };
 
 extern struct cr_options opts;
diff --git a/criu/include/util.h b/criu/include/util.h
index 8eaee33..ea1053b 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -170,6 +170,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 346057a..5dc708f 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -867,6 +867,9 @@  int cr_lazy_pages(bool daemon)
 		}
 	}
 
+	if (close_status_fd())
+		return -1;
+
 	epollfd = prepare_epoll(task_entries->nr_tasks, &events);
 	if (epollfd < 0)
 		return -1;
diff --git a/criu/util.c b/criu/util.c
index 2cf0355..4ecfd4d 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -687,6 +687,21 @@  out:
 	return ret;
 }
 
+int close_status_fd(void)
+{
+	int 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;
@@ -1144,6 +1159,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)