Commit ebd64bdd authored by Andrei Vagin's avatar Andrei Vagin

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: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 0b6f9c79
...@@ -706,12 +706,7 @@ static int pre_dump_loop(int sk, CriuReq *msg) ...@@ -706,12 +706,7 @@ static int pre_dump_loop(int sk, CriuReq *msg)
return dump_using_req(sk, msg->opts); return dump_using_req(sk, msg->opts);
} }
struct ps_info { static int start_page_server_req(int sk, CriuOpts *req, bool daemon_mode)
int pid;
unsigned short port;
};
static int start_page_server_req(int sk, CriuOpts *req)
{ {
int ret = -1, pid, start_pipe[2]; int ret = -1, pid, start_pipe[2];
ssize_t count; ssize_t count;
...@@ -736,35 +731,40 @@ static int start_page_server_req(int sk, CriuOpts *req) ...@@ -736,35 +731,40 @@ static int start_page_server_req(int sk, CriuOpts *req)
pr_debug("Starting page server\n"); 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) if (pid < 0)
goto out_ch; goto out_ch;
info.pid = pid; if (daemon_mode) {
info.port = opts.port; info.pid = pid;
info.port = opts.port;
count = write(start_pipe[1], &info, sizeof(info)); count = write(start_pipe[1], &info, sizeof(info));
if (count != sizeof(info)) if (count != sizeof(info))
goto out_ch; goto out_ch;
}
ret = 0; ret = 0;
out_ch: out_ch:
if (ret < 0 && pid > 0) if (daemon_mode && ret < 0 && pid > 0)
kill(pid, SIGKILL); kill(pid, SIGKILL);
close(start_pipe[1]); close(start_pipe[1]);
exit(ret); exit(ret);
} }
close(start_pipe[1]); close(start_pipe[1]);
wait(&ret);
if (WIFEXITED(ret)) { if (daemon_mode) {
if (WEXITSTATUS(ret)) { wait(&ret);
pr_err("Child exited with an error\n"); 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; goto out;
} }
} else {
pr_err("Child wasn't terminated normally\n");
goto out;
} }
count = read(start_pipe[0], &info, sizeof(info)); count = read(start_pipe[0], &info, sizeof(info));
...@@ -772,11 +772,12 @@ out_ch: ...@@ -772,11 +772,12 @@ out_ch:
if (count != sizeof(info)) if (count != sizeof(info))
goto out; goto out;
success = true;
ps.has_pid = true;
ps.pid = info.pid; ps.pid = info.pid;
ps.has_port = true; ps.has_port = true;
ps.port = info.port; ps.port = info.port;
success = true;
ps.has_pid = true;
resp.ps = &ps; resp.ps = &ps;
pr_debug("Page server started\n"); pr_debug("Page server started\n");
...@@ -803,6 +804,9 @@ static int chk_keepopen_req(CriuReq *msg) ...@@ -803,6 +804,9 @@ static int chk_keepopen_req(CriuReq *msg)
if (msg->type == CRIU_REQ_TYPE__PAGE_SERVER) if (msg->type == CRIU_REQ_TYPE__PAGE_SERVER)
/* This just fork()-s so no leaks */ /* This just fork()-s so no leaks */
return 0; 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 || else if (msg->type == CRIU_REQ_TYPE__CPUINFO_DUMP ||
msg->type == CRIU_REQ_TYPE__CPUINFO_CHECK) msg->type == CRIU_REQ_TYPE__CPUINFO_CHECK)
return 0; return 0;
...@@ -925,6 +929,29 @@ out: ...@@ -925,6 +929,29 @@ out:
return send_criu_msg(sk, &resp); 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) static int handle_cpuinfo(int sk, CriuReq *msg)
{ {
CriuResp resp = CRIU_RESP__INIT; CriuResp resp = CRIU_RESP__INIT;
...@@ -1010,7 +1037,13 @@ more: ...@@ -1010,7 +1037,13 @@ more:
ret = pre_dump_loop(sk, msg); ret = pre_dump_loop(sk, msg);
break; break;
case CRIU_REQ_TYPE__PAGE_SERVER: 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; break;
case CRIU_REQ_TYPE__CPUINFO_DUMP: case CRIU_REQ_TYPE__CPUINFO_DUMP:
case CRIU_REQ_TYPE__CPUINFO_CHECK: case CRIU_REQ_TYPE__CPUINFO_CHECK:
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
#define __CR_PAGE_XFER__H__ #define __CR_PAGE_XFER__H__
#include "pagemap.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); extern int cr_page_server(bool daemon_mode, bool lazy_dump, int cfd);
/* /*
......
...@@ -987,6 +987,19 @@ int cr_page_server(bool daemon_mode, bool lazy_dump, int cfd) ...@@ -987,6 +987,19 @@ int cr_page_server(bool daemon_mode, bool lazy_dump, int cfd)
if (sk == -1) if (sk == -1)
return -1; return -1;
no_server: 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); ret = run_tcp_server(daemon_mode, &ask, cfd, sk);
if (ret != 0) if (ret != 0)
return ret > 0 ? 0 : -1; return ret > 0 ? 0 : -1;
......
...@@ -142,6 +142,9 @@ enum criu_req_type { ...@@ -142,6 +142,9 @@ enum criu_req_type {
FEATURE_CHECK = 9; FEATURE_CHECK = 9;
VERSION = 10; VERSION = 10;
WAIT_PID = 11;
PAGE_SERVER_CHLD = 12;
} }
/* /*
...@@ -176,6 +179,9 @@ message criu_req { ...@@ -176,6 +179,9 @@ message criu_req {
* via RPC. * via RPC.
*/ */
optional criu_features features = 5; optional criu_features features = 5;
/* 'pid' is used for WAIT_PID */
optional uint32 pid = 6;
} }
/* /*
...@@ -196,6 +202,8 @@ message criu_resp { ...@@ -196,6 +202,8 @@ message criu_resp {
optional criu_features features = 8; optional criu_features features = 8;
optional string cr_errmsg = 9; optional string cr_errmsg = 9;
optional criu_version version = 10; optional criu_version version = 10;
optional int32 status = 11;
} }
/* Answer for criu_req_type.VERSION requests */ /* Answer for criu_req_type.VERSION requests */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment