[CRIU] [PATCH 4/9] parasite: stop task on exit from a specified syscall
Andrey Vagin
avagin at openvz.org
Thu Sep 12 09:24:36 EDT 2013
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;
+ }
+
+ 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