[CRIU] [PATCH 7/9] restore: catch task on the exit from sigreturn

Andrey Vagin avagin at openvz.org
Thu Sep 12 09:24:39 EDT 2013


A task is stopped here for unmaping restorer blob and restoring a state.

The method is the same as for parasite. CRIU attaches to processes via
ptrace and start to trace all syscalls.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-restore.c   | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 pie/restorer.c |  1 +
 2 files changed, 91 insertions(+)

diff --git a/cr-restore.c b/cr-restore.c
index 8517672..5a99e88 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -64,6 +64,8 @@
 #include "stats.h"
 #include "tun.h"
 
+#include "parasite-syscall.h"
+
 #include "protobuf.h"
 #include "protobuf/sa.pb-c.h"
 #include "protobuf/timer.pb-c.h"
@@ -1321,6 +1323,89 @@ static int restore_switch_stage(int next_stage)
 	return restore_wait_inprogress_tasks();
 }
 
+static int attach_to_tasks()
+{
+	struct pstree_item *item;
+
+	for_each_pstree_item(item) {
+		pid_t pid = item->pid.real;
+		int status;
+
+		if (item->state == TASK_DEAD)
+			continue;
+
+		if (item->state == TASK_HELPER)
+			continue;
+
+		if (ptrace(PTRACE_ATTACH, pid, NULL, PTRACE_O_TRACEFORK)) {
+			pr_perror("Can't attach to %d", pid);
+			return -1;
+		}
+
+		if (waitpid(pid, &status, 0) < 0) {
+			pr_perror("waitpid() failed");
+			return -1;
+		}
+
+		if (ptrace(PTRACE_CONT, pid, NULL, 0)) {
+			pr_perror("Unable to execute %d", pid);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int unmap_restorer()
+{
+	struct pstree_item *item;
+	int nr = 0;
+
+	for_each_pstree_item(item) {
+		pid_t pid = item->pid.real;
+		int status;
+
+		if (item->state == TASK_DEAD)
+			continue;
+
+		if (item->state == TASK_HELPER)
+			continue;
+
+		if (waitpid(pid, &status, 0) != pid) {
+			pr_perror("waitpid() failed");
+			return -1;
+		}
+
+		if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL)) {
+			pr_perror("ptrace");
+			return -1;
+		}
+
+		nr++;
+	}
+
+	if (parasite_stop_on_syscall(nr, __NR_rt_sigreturn))
+		return -1;
+
+	for_each_pstree_item(item) {
+		pid_t pid = item->pid.real;
+		struct parasite_ctl *ctl;
+
+		if (item->state == TASK_DEAD)
+			continue;
+
+		if (item->state == TASK_HELPER)
+			continue;
+
+		if (ptrace(PTRACE_DETACH, pid, NULL, 0)) {
+			pr_perror("Unable to execute %d", pid);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 static int restore_root_task(struct pstree_item *init)
 {
 	int ret, fd;
@@ -1413,6 +1498,9 @@ static int restore_root_task(struct pstree_item *init)
 	if (ret < 0)
 		goto out_kill;
 
+	if (attach_to_tasks())
+		goto out_kill;
+
 	/* Restore SIGCHLD here to skip SIGCHLD from a network sctip */
 	ret = sigaction(SIGCHLD, &old_act, NULL);
 	if (ret < 0) {
@@ -1436,6 +1524,8 @@ static int restore_root_task(struct pstree_item *init)
 	pr_info("Restore finished successfully. Resuming tasks.\n");
 	futex_set_and_wake(&task_entries->start, CR_STATE_COMPLETE);
 
+	unmap_restorer();
+
 	write_stats(RESTORE_STATS);
 
 	if (!opts.restore_detach)
diff --git a/pie/restorer.c b/pie/restorer.c
index b29ce11..86964b2 100644
--- a/pie/restorer.c
+++ b/pie/restorer.c
@@ -931,6 +931,7 @@ long __export_restore_task(struct task_restore_core_args *args)
 	 * pure assembly since we don't need any additional
 	 * code insns from gcc.
 	 */
+	asm("int $0x03");
 	ARCH_RT_SIGRETURN(new_sp);
 
 core_restore_end:
-- 
1.8.3.1



More information about the CRIU mailing list