[CRIU] [PATCH 4/9] parasite: stop task on exit from a specified syscall

Andrew Vagin avagin at parallels.com
Thu Sep 12 10:44:55 EDT 2013


On Thu, Sep 12, 2013 at 05:24:36PM +0400, Andrey Vagin wrote:
> Currently a parasite stopped on sigreturn for unmaping a parasite blob.
> The same scheme will be used for restorer blob and this function will be
> used to stop on exit from the munmap syscall.
> 
> Signed-off-by: Andrey Vagin <avagin at openvz.org>
> ---
>  include/parasite-syscall.h |  1 +
>  parasite-syscall.c         | 74 ++++++++++++++++++++++++++++++++--------------
>  2 files changed, 53 insertions(+), 22 deletions(-)
> 
> diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
> index aef5f69..3515a30 100644
> --- a/include/parasite-syscall.h
> +++ b/include/parasite-syscall.h
> @@ -114,4 +114,5 @@ extern bool arch_can_dump_task(pid_t pid);
>  extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
>  			       struct vm_area_list *vma_area_list);
>  
> +extern int parasite_stop_on_syscall(int tasks, int sys_nr);
>  #endif /* __CR_PARASITE_SYSCALL_H__ */
> diff --git a/parasite-syscall.c b/parasite-syscall.c
> index b4ad92f..14ec058 100644
> --- a/parasite-syscall.c
> +++ b/parasite-syscall.c
> @@ -759,9 +759,34 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
>  	if (ret)
>  		return -1;
>  
----
> +	ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
> +	if (ret) {
> +		pr_perror("ptrace");
> +		return -1;
> +	}
----
It's the second call of PTRACE_SYSCALL, which will be removed.

> +
> +	if (parasite_stop_on_syscall(1, __NR_rt_sigreturn))
> +		return -1;
> +
> +	return 0;
> +}
> +
> +/*
> + * 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)
> +{
> +	user_regs_struct_t regs;
> +	int status, ret;
> +	pid_t pid;
> +
>  	/* Stop all threads on the enter point in sys_rt_sigreturn */
> -	while (1) {
> -		if (wait4(pid, &status, __WALL, NULL) < 0) {
> +	while (tasks) {
> +		pid = wait4(-1, &status, __WALL, NULL);
> +		if (pid == -1) {
>  			pr_perror("wait4 failed");
>  			return -1;
>  		}
> @@ -779,9 +804,31 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
>  		}
>  
>  		pr_debug("%d is going to execute the syscall %lx\n", pid, REG_SYSCALL_NR(regs));
> -		if (REG_SYSCALL_NR(regs) == __NR_rt_sigreturn) {
> +		if (REG_SYSCALL_NR(regs) == sys_nr) {
> +			/*
> +			 * The process is going to execute the required syscall,
> +			 * the next stop will be on the exit from this syscall
> +			 */
> +			ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
> +			if (ret) {
> +				pr_perror("ptrace");
> +				return -1;
> +			}
> +
> +			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;
> +			}
> +
>  			pr_debug("%d was stopped\n", pid);
> -			break;
> +			tasks--;
> +			continue;
>  		}
>  
>  		ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
> @@ -791,24 +838,7 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
>  		}
>  	}
>  
> -	ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
> -	if (ret) {
> -		pr_perror("ptrace");
> -		return -1;
> -	}
> -
> -	if (wait4(pid, &status, __WALL, NULL) != pid) {
> -		pr_perror("wait4 failed");
> -		return -1;
> -	}
> -
> -	pr_debug("Trap %d\n", pid);
> -	if (!WIFSTOPPED(status)) {
> -		pr_err("%d\n", status);
> -		return -1;
> -	}
> -
> -	return ret;
> +	return 0;
>  }
>  
>  int parasite_cure_remote(struct parasite_ctl *ctl)
> -- 
> 1.8.3.1
> 


More information about the CRIU mailing list