From ebd64bddfeef04d0e80d0e6925b8b92adf5998f0 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Thu, 18 May 2017 03:14:33 +0300 Subject: [PATCH] service: allow to execute page-server as a child process In this case we can wait it and get an exit code. For example, it will be useful for p.haul where one connection is used several times, so we need a way how to understand that page-server exited unexpectedly. v2: don't write ps_info if a start descriptor isn't set Signed-off-by: Andrei Vagin --- criu/cr-service.c | 79 ++++++++++++++++++++++++++++------------ criu/include/page-xfer.h | 5 +++ criu/page-xfer.c | 13 +++++++ images/rpc.proto | 8 ++++ 4 files changed, 82 insertions(+), 23 deletions(-) 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 */