Commit 79d47a93 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

crtoools: add support of stopped tasks (v2)

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: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 2169020b
......@@ -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);
......@@ -1370,11 +1370,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)
/*
* zombies are dumped separately in dump_zombies()
......
......@@ -858,6 +858,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:
......@@ -906,8 +907,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;
......@@ -1394,7 +1404,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:
for (i = 0; i < item->nr_threads; i++) {
pid = item->threads[i].real;
......
......@@ -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:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment