[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