[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