[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