[CRIU] [PATCH 4/6] collect: Factor out recurring collection of threads and children

Pavel Emelyanov xemul at parallels.com
Mon Nov 10 05:05:18 PST 2014


We scan threads and children list several times while freezing
the tree, this is done to avoid race with new threads/kids
appearing.

Factor out the iterations code.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 cr-dump.c | 56 +++++++++++++++++++++++++++++---------------------------
 1 file changed, 29 insertions(+), 27 deletions(-)

diff --git a/cr-dump.c b/cr-dump.c
index a47ec92..7f2dc15 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -975,30 +975,44 @@ err:
 	return -1;
 }
 
-static int collect_threads(struct pstree_item *item)
+static int collect_loop(struct pstree_item *item,
+		int (*collect)(struct pstree_item *))
 {
-	int attempts = NR_ATTEMPTS;
-	int nr_inprogress;
+	int attempts = NR_ATTEMPTS, nr_inprogress = 1;
+
+	/*
+	 * While we scan the proc and seize the children/threads
+	 * new ones can appear (with clone(CLONE_PARENT) or with
+	 * pthread_create). Thus, after one go, we need to repeat
+	 * the scan-and-freeze again collecting new arrivals. As
+	 * new guys may appear again we do NR_ATTEMPTS passes and
+	 * fail to seize the item if new tasks/threads still
+	 * appear.
+	 */
 
-	nr_inprogress = 1;
 	while (nr_inprogress > 0 && attempts) {
 		attempts--;
-
-		nr_inprogress = seize_threads(item);
-		if (nr_inprogress < 0)
-			break;
-
+		nr_inprogress = collect(item);
 	}
 
-	if (nr_inprogress && attempts)
-		return -1;
+	/*
+	 * We may fail to collect items or run out of attempts.
+	 * In the former case nr_inprogress will be negative, in
+	 * the latter -- positive. Thus it's enough just to check
+	 * for "no more new stuff" and say "we're OK" if so.
+	 */
 
-	return 0;
+	return (nr_inprogress == 0) ? 0 : -1;
+}
+
+static int collect_threads(struct pstree_item *item)
+{
+	return collect_loop(item, seize_threads);
 }
 
 static int collect_task(struct pstree_item *item)
 {
-	int ret, nr_inprogress, attempts = NR_ATTEMPTS;
+	int ret;
 
 	ret = collect_threads(item);
 	if (ret < 0)
@@ -1008,20 +1022,8 @@ static int collect_task(struct pstree_item *item)
 		return 0;
 
 	/* Depth-first search (DFS) is used for traversing a process tree. */
-	nr_inprogress = 1;
-	while (nr_inprogress && attempts) {
-		attempts--;
-
-		/*
-		 * Freeze children and children of children, etc.
-		 * Then check again, that nobody is reparented.
-		 */
-		nr_inprogress = get_children(item);
-		if (nr_inprogress < 0)
-			goto err_close;
-	}
-
-	if (attempts == 0)
+	ret = collect_loop(item, get_children);
+	if (ret < 0)
 		goto err_close;
 
 	if ((item->state == TASK_DEAD) && !list_empty(&item->children)) {
-- 
1.8.4.2




More information about the CRIU mailing list