[CRIU] [PATCH 2/2] seize: Simplify processes_to_wait calc

Pavel Emelyanov xemul at virtuozzo.com
Tue Sep 27 10:45:19 PDT 2016


Localize the processes_to_wait calculations in seize.c. In
order to distinguish dead tasks which has already been wait()-ed
from dead tasks that hasn't introduce internal 'zombie' state
for seize_wait_task().

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/cr-exec.c        |  6 ++++++
 criu/include/pid.h    |  1 +
 criu/include/pstree.h |  7 ++++++-
 criu/include/ptrace.h |  2 --
 criu/ptrace.c         | 10 +++++-----
 criu/seize.c          | 23 +++++++++++++++++++----
 6 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/criu/cr-exec.c b/criu/cr-exec.c
index d1424fc..d767b3c 100644
--- a/criu/cr-exec.c
+++ b/criu/cr-exec.c
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include "crtools.h"
 #include "ptrace.h"
+#include "pstree.h"
 #include "parasite-syscall.h"
 #include "vma.h"
 #include "log.h"
@@ -146,6 +147,11 @@ int cr_exec(int pid, char **opt)
 		goto out;
 	}
 
+	if (!is_alive_state(prev_state)) {
+		pr_err("Only can exec on running/stopped tasks\n");
+		goto out;
+	}
+
 	ret = collect_mappings(pid, &vmas, NULL);
 	if (ret) {
 		pr_err("Can't collect vmas for %d\n", pid);
diff --git a/criu/include/pid.h b/criu/include/pid.h
index bf978b4..aa9d502 100644
--- a/criu/include/pid.h
+++ b/criu/include/pid.h
@@ -30,6 +30,7 @@ struct pid {
 #define TASK_STOPPED		0x3
 #define TASK_HELPER		0x4
 #define TASK_THREAD		0x5
+#define TASK_ZOMBIE		0x6
 
 /*
  * When we have to restore a shared resource, we mush select which
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index 3f31d55..d5053f4 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -59,9 +59,14 @@ static inline int shared_fdtable(struct pstree_item *item)
 		item->ids->files_id == item->parent->ids->files_id);
 }
 
+static inline bool is_alive_state(int state)
+{
+	return (state == TASK_ALIVE) || (state == TASK_STOPPED);
+}
+
 static inline bool task_alive(struct pstree_item *i)
 {
-	return (i->pid.state == TASK_ALIVE) || (i->pid.state == TASK_STOPPED);
+	return is_alive_state(i->pid.state);
 }
 
 extern void free_pstree(struct pstree_item *root_item);
diff --git a/criu/include/ptrace.h b/criu/include/ptrace.h
index b30d4ba..72da972 100644
--- a/criu/include/ptrace.h
+++ b/criu/include/ptrace.h
@@ -73,8 +73,6 @@ struct ptrace_peeksiginfo_args {
 
 #define SI_EVENT(_si_code)	(((_si_code) & 0xFFFF) >> 8)
 
-extern int processes_to_wait;
-
 extern int seize_catch_task(pid_t pid);
 extern int seize_wait_task(pid_t pid, pid_t ppid, struct proc_status_creds *creds);
 extern int suspend_seccomp(pid_t pid);
diff --git a/criu/ptrace.c b/criu/ptrace.c
index a449487..155600d 100644
--- a/criu/ptrace.c
+++ b/criu/ptrace.c
@@ -161,7 +161,6 @@ int seize_wait_task(pid_t pid, pid_t ppid, struct proc_status_creds *creds)
 	 * we might need at that early point.
 	 */
 
-	processes_to_wait--;
 try_again:
 
 	ret = wait4(pid, &status, __WALL, NULL);
@@ -171,10 +170,8 @@ try_again:
 		 * if a task is zombie. If we are here from try_again,
 		 * this means that we are tracing this task.
 		 *
-		 * processes_to_wait should be descrimented only once in this
-		 * function if a first wait was success.
+		 * So here we can be only once in this function.
 		 */
-		processes_to_wait++;
 		wait_errno = errno;
 	}
 
@@ -192,7 +189,10 @@ try_again:
 			return -1;
 		}
 
-		return TASK_DEAD;
+		if (ret < 0)
+			return TASK_ZOMBIE;
+		else
+			return TASK_DEAD;
 	}
 
 	if ((ppid != -1) && (creds->ppid != ppid)) {
diff --git a/criu/seize.c b/criu/seize.c
index 0a9a750..56d11d0 100644
--- a/criu/seize.c
+++ b/criu/seize.c
@@ -89,6 +89,10 @@ static int freezer_restore_state(void)
 	return 0;
 }
 
+/* A number of tasks in a freezer cgroup which are not going to be dumped */
+static int processes_to_wait;
+static pid_t *processes_to_wait_pids;
+
 static int seize_cgroup_tree(char *root_path, const char *state)
 {
 	DIR *dir;
@@ -175,10 +179,6 @@ static int seize_cgroup_tree(char *root_path, const char *state)
 	return 0;
 }
 
-/* A number of tasks in a freezer cgroup which are not going to be dumped */
-int processes_to_wait;
-static pid_t *processes_to_wait_pids;
-
 /*
  * A freezer cgroup can contain tasks which will not be dumped
  * and we need to wait them, because the are interupted them by ptrace.
@@ -484,6 +484,11 @@ static int collect_children(struct pstree_item *item)
 			continue;
 		}
 
+		if (ret == TASK_ZOMBIE)
+			ret = TASK_DEAD;
+		else
+			processes_to_wait--;
+
 		dmpi(c)->pi_creds = creds;
 		c->pid.real = pid;
 		c->parent = item;
@@ -701,6 +706,11 @@ static int collect_threads(struct pstree_item *item)
 			continue;
 		}
 
+		if (ret == TASK_ZOMBIE)
+			ret = TASK_DEAD;
+		else
+			processes_to_wait--;
+
 		BUG_ON(item->nr_threads + 1 > nr_threads);
 		item->threads[item->nr_threads].real = pid;
 		item->nr_threads++;
@@ -826,6 +836,11 @@ int collect_pstree(void)
 	if (ret < 0)
 		goto err;
 
+	if (ret == TASK_ZOMBIE)
+		ret = TASK_DEAD;
+	else
+		processes_to_wait--;
+
 	pr_info("Seized task %d, state %d\n", pid, ret);
 	root_item->pid.state = ret;
 	dmpi(root_item)->pi_creds = creds;
-- 
2.5.0



More information about the CRIU mailing list