diff --git a/cr-service.c b/cr-service.c index bbf4edd32..43840d611 100644 --- a/cr-service.c +++ b/cr-service.c @@ -496,7 +496,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; @@ -506,14 +506,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; + } - setproctitle("page-server --rpc --address %s --port %hu", opts.addr, opts.ps_port); + pid = fork(); + if (pid == 0) { + close(start_pipe[0]); - pr_debug("Starting page server\n"); + if (setup_opts_from_req(sk, req)) + goto out_ch; - ret = cr_page_server(true); + setproctitle("page-server --rpc --address %s --port %hu", opts.addr, opts.ps_port); + + 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); + } + + 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 8528cbc16..1c31392d5 100644 --- a/crtools.c +++ b/crtools.c @@ -496,7 +496,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 9e66261e6..d90093204 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 732605c72..eb5e35fc9 100644 --- a/include/util.h +++ b/include/util.h @@ -263,7 +263,7 @@ extern void *shmalloc(size_t bytes); extern void shfree_last(void *ptr); 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 3e38cccb0..3aefb61e0 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 ad153b566..3fae835fd 100644 --- a/util.c +++ b/util.c @@ -560,7 +560,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; @@ -580,6 +580,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");