[CRIU] [PATCH] cr-dump: wait killed processes
Andrey Vagin
avagin at openvz.org
Tue Jul 7 05:47:11 PDT 2015
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 at odin.com>
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
cr-dump.c | 42 +++++++++++++++++++++++++++++++++++++++++-
ptrace.c | 6 ++++--
2 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index 8936a64..1811b76 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -13,6 +13,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vfs.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
#include <sys/sendfile.h>
@@ -854,8 +857,42 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st)
unseize_task(item->pid.real, item->state, st);
+ if (st == TASK_DEAD)
+ return;
+
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)
@@ -865,6 +902,9 @@ static void pstree_switch_state(struct pstree_item *root_item, int st)
pr_info("Unfreezing tasks into %d\n", st);
for_each_pstree_item(item)
unseize_task_and_threads(item, st);
+
+ if (st == TASK_DEAD)
+ pstree_wait(root_item);
}
static pid_t item_ppid(const struct pstree_item *item)
diff --git a/ptrace.c b/ptrace.c
index 4f9e66e..c87c1c8 100644
--- a/ptrace.c
+++ b/ptrace.c
@@ -28,11 +28,13 @@ int unseize_task(pid_t pid, int orig_st, int st)
{
pr_debug("\tUnseizing %d into %d\n", pid, st);
- if (st == TASK_DEAD)
+ if (st == TASK_DEAD) {
kill(pid, SIGKILL);
- else if (st == TASK_STOPPED) {
+ return 0;
+ } else if (st == TASK_STOPPED) {
if (orig_st == TASK_ALIVE)
kill(pid, SIGSTOP);
+ /* PTRACE_SEIZE will restore state of other tasks */
} else if (st == TASK_ALIVE) {
/* do nothing */ ;
} else
--
2.1.0
More information about the CRIU
mailing list