Commit 1fff98f7 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

cr-dump: wait killed processes

The kill syscall queues a signal, but doesn't wait when it will be
handled.

We need to wait processes if we kill them. The user doesn't
expect to find processes after dump in this case.

PTRACE_DETACH returns errors for dead tasks, so we don't need to do it
in these cases.

Cc: Nikita Spiridonov <nspiridonov@odin.com>
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 679aaa56
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/sendfile.h> #include <sys/sendfile.h>
...@@ -853,8 +856,42 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st) ...@@ -853,8 +856,42 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st)
unseize_task(item->pid.real, item->state, st); unseize_task(item->pid.real, item->state, st);
if (st == TASK_DEAD)
return;
for (i = 1; i < item->nr_threads; i++) for (i = 1; i < item->nr_threads; i++)
ptrace(PTRACE_DETACH, item->threads[i].real, NULL, NULL); if (ptrace(PTRACE_DETACH, item->threads[i].real, NULL, NULL))
pr_perror("Unable to detach from %d", item->threads[i].real);
}
static void pstree_wait(struct pstree_item *root_item)
{
struct pstree_item *item = root_item;
int pid, status, i;
for_each_pstree_item(item) {
if (item->state == TASK_DEAD)
continue;
for (i = 0; i < item->nr_threads; i++) {
pid = wait4(-1, &status, __WALL, NULL);
if (pid < 0) {
pr_perror("wait4 failed");
break;
} else {
if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL) {
pr_err("Unexpected exit code %d of %d\n", status, pid);
BUG();
}
}
}
}
pid = wait4(-1, &status, __WALL, NULL);
if (pid > 0) {
pr_err("Unexpected child %d", pid);
BUG();
}
} }
static void pstree_switch_state(struct pstree_item *root_item, int st) static void pstree_switch_state(struct pstree_item *root_item, int st)
...@@ -864,6 +901,9 @@ static void pstree_switch_state(struct pstree_item *root_item, int st) ...@@ -864,6 +901,9 @@ static void pstree_switch_state(struct pstree_item *root_item, int st)
pr_info("Unfreezing tasks into %d\n", st); pr_info("Unfreezing tasks into %d\n", st);
for_each_pstree_item(item) for_each_pstree_item(item)
unseize_task_and_threads(item, st); unseize_task_and_threads(item, st);
if (st == TASK_DEAD)
pstree_wait(root_item);
} }
static pid_t item_ppid(const struct pstree_item *item) static pid_t item_ppid(const struct pstree_item *item)
......
...@@ -27,11 +27,13 @@ int unseize_task(pid_t pid, int orig_st, int st) ...@@ -27,11 +27,13 @@ int unseize_task(pid_t pid, int orig_st, int st)
{ {
pr_debug("\tUnseizing %d into %d\n", pid, st); pr_debug("\tUnseizing %d into %d\n", pid, st);
if (st == TASK_DEAD) if (st == TASK_DEAD) {
kill(pid, SIGKILL); kill(pid, SIGKILL);
else if (st == TASK_STOPPED) { return 0;
} else if (st == TASK_STOPPED) {
if (orig_st == TASK_ALIVE) if (orig_st == TASK_ALIVE)
kill(pid, SIGSTOP); kill(pid, SIGSTOP);
/* PTRACE_SEIZE will restore state of other tasks */
} else if (st == TASK_ALIVE) { } else if (st == TASK_ALIVE) {
/* do nothing */ ; /* do nothing */ ;
} else } else
......
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