[CRIU] [PATCH 3/8] cr-restore: set cr_error to EEXIST if such pid already exists
Ruslan Kuprieiev
kupruser at gmail.com
Mon Dec 1 14:52:38 PST 2014
This is a very common error when using criu.
The problem here is that we need to somehow transfer cr_errno
from one process to another. I suggest using pipe to give
one end to children and read cr_errno on other after restore
is finished.
Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
---
cr-restore.c | 40 ++++++++++++++++++++++++++++++++++++++++
crtools.c | 1 +
include/cr-errno.h | 1 +
include/cr_options.h | 1 +
4 files changed, 43 insertions(+)
diff --git a/cr-restore.c b/cr-restore.c
index 93a6ca6..08b8b66 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -85,6 +85,8 @@
#include "asm/restore.h"
+#include "cr-errno.h"
+
static struct pstree_item *current;
static int restore_task_with_children(void *);
@@ -1412,6 +1414,10 @@ static int restore_task_with_children(void *_arg)
pid = getpid();
if (current->pid.virt != pid) {
pr_err("Pid %d do not match expected %d\n", pid, current->pid.virt);
+ cr_errno = EEXIST;
+ ret = write(opts.errno_fd, &cr_errno, sizeof(cr_errno));
+ if (ret != sizeof(cr_errno))
+ pr_perror("Can't send cr_errno");
goto err;
}
@@ -1501,6 +1507,9 @@ err_fini_mnt:
fini_mnt_ns();
err:
+ ret = write(opts.errno_fd, &cr_errno, sizeof(cr_errno));
+ if (ret != sizeof(cr_errno))
+ perror("Can't send cr_errno");
if (current->parent == NULL)
futex_abort_and_wake(&task_entries->nr_in_progress);
exit(1);
@@ -1857,9 +1866,29 @@ static int prepare_task_entries(void)
return 0;
}
+static int get_cr_errno_fd(void)
+{
+ int p[2];
+
+ if (pipe(p)) {
+ pr_perror("Can't open pipe for cr_errno");
+ return -1;
+ }
+
+ opts.errno_fd = p[1];
+
+ if (fcntl(p[0], F_SETFL, O_NONBLOCK)) {
+ pr_perror("Can't set O_NONBLOCK on pipe");
+ return -1;
+ }
+
+ return p[0];
+}
+
int cr_restore_tasks(void)
{
int ret = -1;
+ int cr_errno_fd = -1, count;
if (cr_plugin_init(CR_PLUGIN_STAGE__RESTORE))
return -1;
@@ -1898,12 +1927,23 @@ int cr_restore_tasks(void)
if (criu_signals_setup() < 0)
goto err;
+ cr_errno_fd = get_cr_errno_fd();
+ if (cr_errno_fd < 0)
+ goto err;
+
if (restore_root_task(root_item) < 0)
goto err;
ret = prepare_cgroup_properties();
err:
+ if (cr_errno_fd) {
+ count = read(cr_errno_fd, &cr_errno, sizeof(cr_errno));
+ if (count != sizeof(cr_errno) && !(count == -1 && errno == EAGAIN))
+ pr_perror("Can't read cr_errno");
+ }
+ close_safe(&cr_errno_fd);
+ close_safe(&opts.errno_fd);
fini_cgroup();
cr_plugin_fini(CR_PLUGIN_STAGE__RESTORE, ret);
return ret;
diff --git a/crtools.c b/crtools.c
index 0ac667c..3f6231d 100644
--- a/crtools.c
+++ b/crtools.c
@@ -57,6 +57,7 @@ void init_opts(void)
opts.cpu_cap = CPU_CAP_DEFAULT;
opts.manage_cgroups = false;
opts.ps_socket = -1;
+ opts.errno_fd = -1;
}
static int parse_ns_string(const char *ptr)
diff --git a/include/cr-errno.h b/include/cr-errno.h
index bec72a8..f86bba8 100644
--- a/include/cr-errno.h
+++ b/include/cr-errno.h
@@ -4,6 +4,7 @@ extern int cr_errno;
/*
* List of symbolic error names:
* ESRCH - no process can be found corresponding to that specified by pid
+ * EEXIST - process with such pid already exists
*/
#endif /* __CR_ERRNO_H__ */
diff --git a/include/cr_options.h b/include/cr_options.h
index a9f9e92..a32584f 100644
--- a/include/cr_options.h
+++ b/include/cr_options.h
@@ -58,6 +58,7 @@ struct cr_options {
char *new_global_cg_root;
struct list_head new_cgroup_roots;
bool aufs; /* auto-deteced, not via cli */
+ int errno_fd; /* pipe used to trasfer cr_errno */
};
extern struct cr_options opts;
--
1.9.3
More information about the CRIU
mailing list