rpc/log: return first error always

Use shared first error buffer to return correct
first error in rpc.

Fixes: #338

Signed-off-by: Ivan Pravdin <ipravdin.official@gmail.com>
This commit is contained in:
Ivan Pravdin 2025-05-06 22:40:25 -04:00 committed by Andrei Vagin
parent a79b33d0c5
commit 922754dffd
3 changed files with 48 additions and 2 deletions

View file

@ -895,6 +895,11 @@ static int check(int sk, CriuOpts *req)
resp.type = CRIU_REQ_TYPE__CHECK;
if (log_keep_err()) {
pr_perror("Can't tune log");
goto out;
}
pid = fork();
if (pid < 0) {
pr_perror("Can't fork");
@ -919,6 +924,7 @@ static int check(int sk, CriuOpts *req)
resp.success = true;
out:
set_resp_err(&resp);
return send_criu_msg(sk, &resp);
}
@ -927,6 +933,11 @@ static int pre_dump_using_req(int sk, CriuOpts *req, bool single)
int pid, status;
bool success = false;
if (log_keep_err()) {
pr_perror("Can't tune log");
goto out;
}
pid = fork();
if (pid < 0) {
pr_perror("Can't fork");
@ -1005,6 +1016,11 @@ static int start_page_server_req(int sk, CriuOpts *req, bool daemon_mode)
CriuPageServerInfo ps = CRIU_PAGE_SERVER_INFO__INIT;
struct ps_info info;
if (log_keep_err()) {
pr_perror("Can't tune log");
goto out;
}
if (pipe(start_pipe)) {
pr_perror("No start pipe");
goto out;
@ -1078,6 +1094,7 @@ static int start_page_server_req(int sk, CriuOpts *req, bool daemon_mode)
out:
resp.type = CRIU_REQ_TYPE__PAGE_SERVER;
resp.success = success;
set_resp_err(&resp);
return send_criu_msg(sk, &resp);
}
@ -1252,6 +1269,11 @@ static int handle_cpuinfo(int sk, CriuReq *msg)
bool success = false;
int pid, status;
if (log_keep_err()) {
pr_perror("Can't tune log");
goto out;
}
pid = fork();
if (pid < 0) {
pr_perror("Can't fork");
@ -1301,7 +1323,7 @@ static int handle_cpuinfo(int sk, CriuReq *msg)
out:
resp.type = msg->type;
resp.success = success;
set_resp_err(&resp);
return send_criu_msg(sk, &resp);
}

View file

@ -10,6 +10,7 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <sys/mman.h>
#include <fcntl.h>
@ -114,6 +115,9 @@ static struct str_and_lock *first_err;
int log_keep_err(void)
{
if (first_err)
return 0;
first_err = shmalloc(sizeof(struct str_and_lock));
if (first_err == NULL)
return -1;

View file

@ -40,7 +40,7 @@ class test:
resp.ParseFromString(self.s.recv(self._MAX_MSG_SIZE))
return resp
def check_resp(self, resp, typ, err):
def check_resp(self, resp, typ, err, errmsg = None):
if resp.type != typ:
raise Exception('Unexpected response type ' + str(resp.type))
@ -49,6 +49,9 @@ class test:
if err and resp.cr_errno != err:
raise Exception('Unexpected cr_errno ' + str(resp.cr_errno))
if errmsg and errmsg not in resp.cr_errmsg:
raise Exception('Unexpected cr_msg \'' + str(resp.cr_errmsg) + '\'')
def no_process(self):
print('Try to dump unexisting process')
@ -131,12 +134,29 @@ class test:
self.check_resp(resp, rpc.EMPTY, None)
print('Success')
def child_first_err(self):
print('Receive correct first error message')
req = self.get_base_req()
req.type = rpc.CHECK
# mntns_compat_mode options is only allowed on restore
req.opts.mntns_compat_mode = True
self.send_req(req)
resp = self.recv_resp()
self.check_resp(resp, rpc.CHECK, None, "Option --mntns-compat-mode is only valid on restore\n")
print('Success')
def run(self):
self.no_process()
self.process_exists()
self.bad_options()
self.bad_request()
self.child_first_err()
t = test()