[CRIU] [PATCH 3/3] crtoools: add support of stopped tasks (v2)

Andrey Vagin avagin at openvz.org
Thu Sep 26 10:08:21 EDT 2013


Currently we catch processes on the exit point from sigreturn.
If a task must be restored in the stopped state, we can send SIGSTOP
before detaching from it.

v2: add more descriptive comment about skipping SIGSTOP in ptrace.c
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-dump.c    |  7 +------
 cr-restore.c | 15 +++++++++++++--
 ptrace.c     | 31 ++++++++++++++++++++++++++++++-
 test/zdtm.sh |  1 +
 4 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index ebd2cc5..284c1e3 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -660,7 +660,7 @@ static int dump_task_core_all(struct pstree_item *item,
 
 	strncpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
 	core->tc->flags = stat->flags;
-	core->tc->task_state = TASK_ALIVE;
+	core->tc->task_state = item->state;
 	core->tc->exit_code = 0;
 
 	ret = dump_thread_core(pid, core, &misc->ti);
@@ -1364,11 +1364,6 @@ static int dump_one_task(struct pstree_item *item)
 	pr_info("Dumping task (pid: %d)\n", pid);
 	pr_info("========================================\n");
 
-	if (item->state == TASK_STOPPED) {
-		pr_err("Stopped tasks are not supported\n");
-		return -1;
-	}
-
 	if (item->state == TASK_DEAD)
 		return 0;
 
diff --git a/cr-restore.c b/cr-restore.c
index 419f14e..cd1e8cb 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -861,6 +861,7 @@ static int restore_one_task(int pid, CoreEntry *core)
 
 	switch ((int)core->tc->task_state) {
 	case TASK_ALIVE:
+	case TASK_STOPPED:
 		ret = restore_one_alive_task(pid, core);
 		break;
 	case TASK_DEAD:
@@ -909,8 +910,17 @@ static inline int fork_with_pid(struct pstree_item *item)
 
 		item->state = ca.core->tc->task_state;
 
-		if (item->state == TASK_DEAD)
+		switch (item->state) {
+		case TASK_ALIVE:
+		case TASK_STOPPED:
+			break;
+		case TASK_DEAD:
 			item->parent->rst->nr_zombies++;
+			break;
+		default:
+			pr_err("Unknown task state %d\n", item->state);
+			return -1;
+		}
 	} else
 		ca.core = NULL;
 
@@ -1389,7 +1399,8 @@ static void finalize_restore(int status)
 
 		xfree(ctl);
 
-		/* TODO restore the process state */
+		if (item->state == TASK_STOPPED)
+			kill(item->pid.real, SIGSTOP);
 detach:
 #ifdef CR_DEBUG
 		BUG_ON(status < 0);
diff --git a/ptrace.c b/ptrace.c
index 4b6b84c..f3d2056 100644
--- a/ptrace.c
+++ b/ptrace.c
@@ -136,8 +136,37 @@ try_again:
 
 	if (si.si_signo == SIGTRAP)
 		return TASK_ALIVE;
-	else if (si.si_signo == SIGSTOP)
+	else if (si.si_signo == SIGSTOP) {
+		/*
+		 * PTRACE_SEIZE doesn't affect signal or group stop state.
+		 * Currently ptrace reported that task is in stopped state.
+		 * We need to start task again, and it will be trapped
+		 * immediately, because we sent PTRACE_INTERRUPT to it.
+		 */
+		ret = ptrace(PTRACE_CONT, pid, 0, 0);
+		if (ret) {
+			pr_perror("Unable to start process");
+			goto err;
+		}
+
+		ret = wait4(pid, &status, __WALL, NULL);
+		if (ret < 0) {
+			pr_perror("SEIZE %d: can't wait task", pid);
+			goto err;
+		}
+
+		if (ret != pid) {
+			pr_err("SEIZE %d: wrong task attached (%d)\n", pid, ret);
+			goto err;
+		}
+
+		if (!WIFSTOPPED(status)) {
+			pr_err("SEIZE %d: task not stopped after seize\n", pid);
+			goto err;
+		}
+
 		return TASK_STOPPED;
+	}
 
 	pr_err("SEIZE %d: unsupported stop signal %d\n", pid, si.si_signo);
 err:
diff --git a/test/zdtm.sh b/test/zdtm.sh
index e1be1a5..ebc53fc 100755
--- a/test/zdtm.sh
+++ b/test/zdtm.sh
@@ -94,6 +94,7 @@ static/sk-netlink
 static/proc-self
 static/grow_map
 static/grow_map02
+static/stopped
 "
 # Duplicate list with ns/ prefix
 TEST_LIST=$TEST_LIST$(echo $TEST_LIST | tr ' ' '\n' | sed 's#^#ns/#')
-- 
1.8.3.1



More information about the CRIU mailing list