[CRIU] [PATCH 3/8] cr-restore: set cr_error to EEXIST if such pid already exists
Pavel Emelyanov
xemul at parallels.com
Tue Dec 2 00:39:19 PST 2014
On 12/02/2014 01:52 AM, Ruslan Kuprieiev wrote:
> 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.
No, thanks :) We have two better ways of transferring 4 bytes :)
First is the exit code of the failed sub-task. We wait() for them
in parents anyway, so propagating the cr_errno there would work.
The second option is by putting the value into task_entries
shared area.
> 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;
>
More information about the CRIU
mailing list