[CRIU] [PATCH 3/3] page-server: Don't setup options in parent task

Pavel Emelyanov xemul at parallels.com
Thu Sep 4 09:39:07 PDT 2014


When service starts page server all the preparations (log, wdir, img dir, etc.)
happen in parent task, then we fork page server.

This is OK for now, but when we will serve several requests per connection, all
these resources would be leaked in parent.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 cr-service.c        | 29 ++++++++++++++++++++++++-----
 crtools.c           |  2 +-
 include/page-xfer.h |  2 +-
 include/util.h      |  2 +-
 page-xfer.c         |  4 ++--
 util.c              |  8 +++++++-
 6 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/cr-service.c b/cr-service.c
index 06b531c..46410fe 100644
--- a/cr-service.c
+++ b/cr-service.c
@@ -499,7 +499,7 @@ static int pre_dump_loop(int sk, CriuReq *msg)
 
 static int start_page_server_req(int sk, CriuOpts *req)
 {
-	int ret;
+	int ret, pid, start_pipe[2];
 	bool success = false;
 	CriuResp resp = CRIU_RESP__INIT;
 	CriuPageServerInfo ps = CRIU_PAGE_SERVER_INFO__INIT;
@@ -509,14 +509,33 @@ static int start_page_server_req(int sk, CriuOpts *req)
 		goto out;
 	}
 
-	if (setup_opts_from_req(sk, req))
+	if (pipe(start_pipe)) {
+		pr_perror("No start pipe");
 		goto out;
+	}
+
+	pid = fork();
+	if (pid == 0) {
+		close(start_pipe[0]);
+
+		if (setup_opts_from_req(sk, req))
+			goto out_ch;
 
-	setproctitle("page-server --rpc --address %s --port %hu", opts.addr, opts.ps_port);
+		setproctitle("page-server --rpc --address %s --port %hu", opts.addr, opts.ps_port);
 
-	pr_debug("Starting page server\n");
+		pr_debug("Starting page server\n");
+
+		ret = cr_page_server(true, start_pipe[1]);
+out_ch:
+		write(start_pipe[1], &ret, sizeof(ret));
+		close(start_pipe[1]);
+		exit(0);
+	}
 
-	ret = cr_page_server(true);
+	close(start_pipe[1]);
+	wait(NULL);
+	ret = -1;
+	read(start_pipe[0], &ret, sizeof(ret));
 	if (ret > 0) {
 		success = true;
 		ps.has_pid = true;
diff --git a/crtools.c b/crtools.c
index 130cd29..0c56679 100644
--- a/crtools.c
+++ b/crtools.c
@@ -502,7 +502,7 @@ int main(int argc, char *argv[], char *envp[])
 	}
 
 	if (!strcmp(argv[optind], "page-server"))
-		return cr_page_server(opts.restore_detach) > 0 ? 0 : 1;
+		return cr_page_server(opts.restore_detach, -1) > 0 ? 0 : 1;
 
 	if (!strcmp(argv[optind], "service"))
 		return cr_service(opts.restore_detach);
diff --git a/include/page-xfer.h b/include/page-xfer.h
index 9e66261..d900932 100644
--- a/include/page-xfer.h
+++ b/include/page-xfer.h
@@ -2,7 +2,7 @@
 #define __CR_PAGE_XFER__H__
 #include "page-read.h"
 
-extern int cr_page_server(bool daemon_mode);
+extern int cr_page_server(bool daemon_mode, int cfd);
 
 /*
  * page_xfer -- transfer pages into image file.
diff --git a/include/util.h b/include/util.h
index 908172a..fcf50a9 100644
--- a/include/util.h
+++ b/include/util.h
@@ -264,7 +264,7 @@ extern void shfree_last(void *ptr);
 extern int run_scripts(char *action);
 
 extern int cr_system(int in, int out, int err, char *cmd, char *const argv[]);
-extern int cr_daemon(int nochdir, int noclose);
+extern int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd);
 extern int is_root_user(void);
 
 static inline bool dir_dots(struct dirent *de)
diff --git a/page-xfer.c b/page-xfer.c
index 3e38ccc..3aefb61 100644
--- a/page-xfer.c
+++ b/page-xfer.c
@@ -254,7 +254,7 @@ static int get_sockaddr_in(struct sockaddr_in *addr)
 	return 0;
 }
 
-int cr_page_server(bool daemon_mode)
+int cr_page_server(bool daemon_mode, int cfd)
 {
 	int sk = -1, ask = -1, ret;
 	struct sockaddr_in saddr, caddr;
@@ -292,7 +292,7 @@ int cr_page_server(bool daemon_mode)
 
 no_server:
 	if (daemon_mode) {
-		ret = cr_daemon(1, 0);
+		ret = cr_daemon(1, 0, &ask, cfd);
 		if (ret == -1) {
 			pr_perror("Can't run in the background");
 			goto out;
diff --git a/util.c b/util.c
index 3b31537..f2e79c6 100644
--- a/util.c
+++ b/util.c
@@ -596,7 +596,7 @@ out:
 	return ret;
 }
 
-int cr_daemon(int nochdir, int noclose)
+int cr_daemon(int nochdir, int noclose, int *keep_fd, int close_fd)
 {
 	int pid;
 
@@ -616,6 +616,12 @@ int cr_daemon(int nochdir, int noclose)
 	if (!noclose) {
 		int fd;
 
+		if (close_fd != -1)
+			close(close_fd);
+
+		if (*keep_fd != -1)
+			*keep_fd = dup2(*keep_fd, 3);
+
 		fd = open("/dev/null", O_RDWR);
 		if (fd < 0) {
 			pr_perror("Can't open /dev/null");
-- 
1.8.4.2




More information about the CRIU mailing list