[CRIU] [PATCH 3/8] cr-restore: set cr_error to EEXIST if such pid already exists

Ruslan Kuprieiev kupruser at gmail.com
Tue Dec 2 01:54:09 PST 2014


On 12/02/2014 10:39 AM, Pavel Emelyanov wrote:
> 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.
>

Oh, I see.
Thanks!

>> 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