[CRIU] [PATCH] ptrace: say to parasite_stop_on_syscall where is we now

Tycho Andersen tycho.andersen at canonical.com
Fri Sep 19 12:13:54 PDT 2014


On Fri, Sep 19, 2014 at 11:08:44PM +0400, Andrew Vagin wrote:
> On restore parasite_stop_on_syscall() can be called after PTRACE_SYSCALL
> and after a breakpoint. parasite_stop_on_syscall() must be called only
> after PTRACE_SYSCALL, so all tests where is one process stuck.
> 
> Reported-by: Mr Jenkins
> Signed-off-by: Andrew Vagin <avagin at openvz.org>

This fixes the issue that I mentioned in the other thread, thanks.

Acked-by: Tycho Andersen <tycho.andersen at canonical.com>

> ---
>  cr-restore.c               | 19 +++++++++++++------
>  include/parasite-syscall.h | 14 +++++++++++++-
>  parasite-syscall.c         | 46 ++++++++++++++++------------------------------
>  3 files changed, 42 insertions(+), 37 deletions(-)
> 
> diff --git a/cr-restore.c b/cr-restore.c
> index 954e817..809564b 100644
> --- a/cr-restore.c
> +++ b/cr-restore.c
> @@ -1540,7 +1540,7 @@ static int restore_switch_stage(int next_stage)
>  	return restore_wait_inprogress_tasks();
>  }
>  
> -static int attach_to_tasks(bool root_seized)
> +static int attach_to_tasks(bool root_seized, enum trace_flags *flag)
>  {
>  	struct pstree_item *item;
>  
> @@ -1584,9 +1584,14 @@ static int attach_to_tasks(bool root_seized)
>  				return -1;
>  
>  			/* A breakpoint was not set */
> -			if (ret == 0 && ptrace(PTRACE_SYSCALL, pid, NULL, NULL)) {
> -				pr_perror("Unable to start %d", pid);
> -				return -1;
> +			if (ret > 0)
> +				*flag = TRACE_EXIT;
> +			else {
> +				*flag = TRACE_ENTER;
> +				if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL)) {
> +					pr_perror("Unable to start %d", pid);
> +					return -1;
> +				}
>  			}
>  		}
>  	}
> @@ -1644,6 +1649,7 @@ static void ignore_kids(void)
>  
>  static int restore_root_task(struct pstree_item *init)
>  {
> +	enum trace_flags flag = TRACE_ALL;
>  	int ret, fd;
>  
>  	fd = open("/proc", O_DIRECTORY | O_RDONLY);
> @@ -1760,13 +1766,14 @@ static int restore_root_task(struct pstree_item *init)
>  
>  	timing_stop(TIME_RESTORE);
>  
> -	ret = attach_to_tasks(root_as_sibling);
> +	ret = attach_to_tasks(root_as_sibling, &flag);
>  
>  	pr_info("Restore finished successfully. Resuming tasks.\n");
>  	futex_set_and_wake(&task_entries->start, CR_STATE_COMPLETE);
>  
>  	if (ret == 0)
> -		ret = parasite_stop_on_syscall(task_entries->nr_threads, __NR_rt_sigreturn);
> +		ret = parasite_stop_on_syscall(task_entries->nr_threads,
> +						__NR_rt_sigreturn, flag);
>  
>  	/*
>  	 * finalize_restore() always detaches from processes and
> diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
> index fbc5614..5d2df08 100644
> --- a/include/parasite-syscall.h
> +++ b/include/parasite-syscall.h
> @@ -125,7 +125,19 @@ extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
>  			       struct vm_area_list *vma_area_list);
>  #endif
>  
> -extern int parasite_stop_on_syscall(int tasks, int sys_nr);
> +/*
> + * The PTRACE_SYSCALL will trap task twice -- on
> + * enter into and on exit from syscall. If we trace
> + * a single task, we may skip half of all getregs
> + * calls -- on exit we don't need them.
> + */
> +enum trace_flags {
> +	TRACE_ALL,
> +	TRACE_ENTER,
> +	TRACE_EXIT,
> +};
> +
> +extern int parasite_stop_on_syscall(int tasks, int sys_nr, enum trace_flags trace);
>  extern int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr);
>  
>  #endif /* __CR_PARASITE_SYSCALL_H__ */
> diff --git a/parasite-syscall.c b/parasite-syscall.c
> index 88c9d42..37e9db0 100644
> --- a/parasite-syscall.c
> +++ b/parasite-syscall.c
> @@ -827,6 +827,7 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
>  	pid_t pid = ctl->pid.real;
>  	user_regs_struct_t regs;
>  	int status, ret = 0;
> +	enum trace_flags flag;
>  
>  	/* stop getting chld from parasite -- we're about to step-by-step it */
>  	if (restore_child_handler())
> @@ -873,27 +874,20 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
>  	ret = ptrace_set_breakpoint(pid, ctl->sigreturn_addr);
>  	if (ret < 0)
>  		return ret;
> -	if (ret > 0) {
> -		pid = wait4(pid, &status, __WALL, NULL);
> -		if (pid == -1) {
> -			pr_perror("wait4 failed");
> -			return -1;
> -		}
> -
> -		if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGTRAP) {
> -			pr_err("Task is in unexpected state: %x\n", status);
> -			return -1;
> +	if (ret > 0)
> +		flag = TRACE_EXIT;
> +	else {
> +		/* Start tracing syscalls */
> +		ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
> +		if (ret) {
> +		       pr_perror("ptrace");
> +		       return -1;
>  		}
> -	}
>  
> -	/* Start tracing syscalls */
> -	ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
> -	if (ret) {
> -		pr_perror("ptrace");
> -		return -1;
> +		flag = TRACE_ENTER;
>  	}
>  
> -	if (parasite_stop_on_syscall(1, __NR_rt_sigreturn))
> +	if (parasite_stop_on_syscall(1, __NR_rt_sigreturn, flag))
>  		return -1;
>  
>  	/*
> @@ -905,28 +899,20 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
>  	return 0;
>  }
>  
> -#define TRACE_ALL	1
> -#define TRACE_ENTER	2
> -#define TRACE_EXIT	3
> -
>  /*
>   * Trap tasks on the exit from the specified syscall
>   *
>   * tasks - number of processes, which should be trapped
>   * sys_nr - the required syscall number
>   */
> -int parasite_stop_on_syscall(int tasks, const int sys_nr)
> +int parasite_stop_on_syscall(int tasks, const int sys_nr, enum trace_flags trace)
>  {
>  	user_regs_struct_t regs;
>  	int status, ret;
>  	pid_t pid;
> -	/*
> -	 * The PTRACE_SYSCALL will trap task twice -- on
> -	 * enter into and on exit from syscall. If we trace
> -	 * a single task, we may skip half of all getregs
> -	 * calls -- on exit we don't need them.
> -	 */
> -	int trace = (tasks == 1 ? TRACE_ENTER : TRACE_ALL);
> +
> +	if (tasks > 1)
> +		trace = TRACE_ALL;
>  
>  	/* Stop all threads on the enter point in sys_rt_sigreturn */
>  	while (tasks) {
> @@ -1061,7 +1047,7 @@ int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr)
>  	if (ret)
>  		goto err;
>  
> -	ret = parasite_stop_on_syscall(1, __NR_munmap);
> +	ret = parasite_stop_on_syscall(1, __NR_munmap, TRACE_ENTER);
>  
>  	if (restore_thread_ctx(pid, &ctl->orig))
>  		ret = -1;
> -- 
> 1.9.3
> 
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu


More information about the CRIU mailing list