[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