diff --git a/criu/cr-service.c b/criu/cr-service.c index 9172a8c4b..33d417329 100644 --- a/criu/cr-service.c +++ b/criu/cr-service.c @@ -706,12 +706,7 @@ static int pre_dump_loop(int sk, CriuReq *msg) return dump_using_req(sk, msg->opts); } -struct ps_info { - int pid; - unsigned short port; -}; - -static int start_page_server_req(int sk, CriuOpts *req) +static int start_page_server_req(int sk, CriuOpts *req, bool daemon_mode) { int ret = -1, pid, start_pipe[2]; ssize_t count; @@ -736,35 +731,40 @@ static int start_page_server_req(int sk, CriuOpts *req) pr_debug("Starting page server\n"); - pid = cr_page_server(true, false, start_pipe[1]); + pid = cr_page_server(daemon_mode, false, start_pipe[1]); if (pid < 0) goto out_ch; - info.pid = pid; - info.port = opts.port; + if (daemon_mode) { + info.pid = pid; + info.port = opts.port; - count = write(start_pipe[1], &info, sizeof(info)); - if (count != sizeof(info)) - goto out_ch; + count = write(start_pipe[1], &info, sizeof(info)); + if (count != sizeof(info)) + goto out_ch; + } ret = 0; out_ch: - if (ret < 0 && pid > 0) + if (daemon_mode && ret < 0 && pid > 0) kill(pid, SIGKILL); close(start_pipe[1]); exit(ret); } close(start_pipe[1]); - wait(&ret); - if (WIFEXITED(ret)) { - if (WEXITSTATUS(ret)) { - pr_err("Child exited with an error\n"); + + if (daemon_mode) { + wait(&ret); + if (WIFEXITED(ret)) { + if (WEXITSTATUS(ret)) { + pr_err("Child exited with an error\n"); + goto out; + } + } else { + pr_err("Child wasn't terminated normally\n"); goto out; } - } else { - pr_err("Child wasn't terminated normally\n"); - goto out; } count = read(start_pipe[0], &info, sizeof(info)); @@ -772,11 +772,12 @@ out_ch: if (count != sizeof(info)) goto out; - success = true; - ps.has_pid = true; ps.pid = info.pid; ps.has_port = true; ps.port = info.port; + + success = true; + ps.has_pid = true; resp.ps = &ps; pr_debug("Page server started\n"); @@ -803,6 +804,9 @@ static int chk_keepopen_req(CriuReq *msg) if (msg->type == CRIU_REQ_TYPE__PAGE_SERVER) /* This just fork()-s so no leaks */ return 0; + if (msg->type == CRIU_REQ_TYPE__PAGE_SERVER_CHLD) + /* This just fork()-s so no leaks */ + return 0; else if (msg->type == CRIU_REQ_TYPE__CPUINFO_DUMP || msg->type == CRIU_REQ_TYPE__CPUINFO_CHECK) return 0; @@ -925,6 +929,29 @@ out: return send_criu_msg(sk, &resp); } +static int handle_wait_pid(int sk, int pid) +{ + CriuResp resp = CRIU_RESP__INIT; + bool success = false; + int status; + + if (waitpid(pid, &status, 0) == -1) { + resp.cr_errno = errno; + pr_perror("Unable to wait %d", pid); + goto out; + } + + resp.status = status; + resp.has_status = true; + + success = true; +out: + resp.type = CRIU_REQ_TYPE__WAIT_PID; + resp.success = success; + + return send_criu_msg(sk, &resp); +} + static int handle_cpuinfo(int sk, CriuReq *msg) { CriuResp resp = CRIU_RESP__INIT; @@ -1010,7 +1037,13 @@ more: ret = pre_dump_loop(sk, msg); break; case CRIU_REQ_TYPE__PAGE_SERVER: - ret = start_page_server_req(sk, msg->opts); + ret = start_page_server_req(sk, msg->opts, true); + break; + case CRIU_REQ_TYPE__PAGE_SERVER_CHLD: + ret = start_page_server_req(sk, msg->opts, false); + break; + case CRIU_REQ_TYPE__WAIT_PID: + ret = handle_wait_pid(sk, msg->pid); break; case CRIU_REQ_TYPE__CPUINFO_DUMP: case CRIU_REQ_TYPE__CPUINFO_CHECK: diff --git a/criu/include/page-xfer.h b/criu/include/page-xfer.h index 89e7ea9f0..ee90ae65a 100644 --- a/criu/include/page-xfer.h +++ b/criu/include/page-xfer.h @@ -2,6 +2,11 @@ #define __CR_PAGE_XFER__H__ #include "pagemap.h" +struct ps_info { + int pid; + unsigned short port; +}; + extern int cr_page_server(bool daemon_mode, bool lazy_dump, int cfd); /* diff --git a/criu/page-xfer.c b/criu/page-xfer.c index 86f1e6692..df4eb2877 100644 --- a/criu/page-xfer.c +++ b/criu/page-xfer.c @@ -987,6 +987,19 @@ int cr_page_server(bool daemon_mode, bool lazy_dump, int cfd) if (sk == -1) return -1; no_server: + + if (!daemon_mode && cfd >= 0) { + struct ps_info info = {.pid = getpid(), .port = opts.port}; + int count; + + count = write(cfd, &info, sizeof(info)); + close_safe(&cfd); + if (count != sizeof(info)) { + pr_perror("Unable to write ps_info"); + exit(1); + } + } + ret = run_tcp_server(daemon_mode, &ask, cfd, sk); if (ret != 0) return ret > 0 ? 0 : -1; diff --git a/images/rpc.proto b/images/rpc.proto index 48e42e26e..71f47d594 100644 --- a/images/rpc.proto +++ b/images/rpc.proto @@ -142,6 +142,9 @@ enum criu_req_type { FEATURE_CHECK = 9; VERSION = 10; + + WAIT_PID = 11; + PAGE_SERVER_CHLD = 12; } /* @@ -176,6 +179,9 @@ message criu_req { * via RPC. */ optional criu_features features = 5; + + /* 'pid' is used for WAIT_PID */ + optional uint32 pid = 6; } /* @@ -196,6 +202,8 @@ message criu_resp { optional criu_features features = 8; optional string cr_errmsg = 9; optional criu_version version = 10; + + optional int32 status = 11; } /* Answer for criu_req_type.VERSION requests */