[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