[CRIU] [PATCH 2/2] seize: don't catch all processes from a freezer cgroup
Andrey Vagin
avagin at openvz.org
Tue Oct 27 04:13:21 PDT 2015
From: Andrew Vagin <avagin at openvz.org>
It can contain extra processes, but criu dumps only descendants
of a specified process.
seize_catch_task() attaches to a process and sends the interrupt signal,
then seize_wait_task() waits when a process will be interrupted.
Currently if a group contains extra processes, criu attaches to them,
but doesn't wait them, so waitpid(-1, ...) can return one of this processes,
but we don't expect this.
Reported-by: @jcarnus
Signed-off-by: Andrew Vagin <avagin at openvz.org>
---
seize.c | 99 +++++++++++++++++++++++++++++++++++++-----------------------
test/zdtm.sh | 2 +-
2 files changed, 62 insertions(+), 39 deletions(-)
diff --git a/seize.c b/seize.c
index 0f93b84..e1caebb 100644
--- a/seize.c
+++ b/seize.c
@@ -79,12 +79,68 @@ static int freezer_restore_state(void)
return 0;
}
-static int freeze_processes(void)
+static int __freeze_processes(pid_t pid, const char *state)
{
- int i, ret, fd, exit_code = -1;
+ pid_t *children = NULL;
+ int nr_children = 0;
+ int ret, off = -1, exit_code = -1;
+ struct pid *threads = NULL;
+
+ while (1) {
+ int nr_threads = 0;
+ int i;
+
+ if (parse_threads(pid, &threads, &nr_threads))
+ goto err;
+
+ for (i = 0; i < nr_threads; i++) {
+ pid_t tid = threads[i].real;
+
+ /*
+ * Here we are going to skip tasks which are already traced.
+ * Ptraced tasks looks like children for us, so if
+ * a task isn't ptraced yet, waitpid() will return a error.
+ */
+ ret = wait4(tid, NULL, __WALL | WNOHANG, NULL);
+ if (ret == 0)
+ continue;
+
+ if (seize_catch_task(tid) && state == frozen) {
+ char buf[] = "/proc/XXXXXXXXXX/exe";
+ struct stat st;
+
+ /* skip kernel threads and zombies */
+ snprintf(buf, sizeof(buf), "/proc/%d/exe", pid);
+ if (stat(buf, &st) == -1 && errno == ENOENT)
+ continue;
+
+ goto err;
+ }
+ }
+ xfree(threads);
+ threads = NULL;
+
+ if (parse_children(pid, &children, &nr_children))
+ goto err;
+
+ off++;
+ if (off >= nr_children)
+ break;
+ pid = children[off];
+ }
+
+ exit_code = 0;
+err:
+ xfree(children);
+ xfree(threads);
+ return exit_code;
+}
+
+static int freeze_processes(int pid)
+{
+ int i, fd, exit_code = -1;
char path[PATH_MAX];
const char *state = thawed;
- FILE *f;
snprintf(path, sizeof(path), "%s/freezer.state", opts.freeze_cgroup);
fd = open(path, O_RDWR);
@@ -121,41 +177,8 @@ static int freeze_processes(void)
* New tasks can appear while a freezer state isn't
* frozen, so we need to catch all new tasks.
*/
- snprintf(path, sizeof(path), "%s/tasks", opts.freeze_cgroup);
- f = fopen(path, "r");
- if (f == NULL) {
- pr_perror("Unable to open %s", path);
+ if (__freeze_processes(pid, state))
goto err;
- }
- while (fgets(path, sizeof(path), f)) {
- pid_t pid;
-
- pid = atoi(path);
-
- /*
- * Here we are going to skip tasks which are already traced.
- * Ptraced tasks looks like children for us, so if
- * a task isn't ptraced yet, waitpid() will return a error.
- */
- ret = wait4(pid, NULL, __WALL | WNOHANG, NULL);
- if (ret == 0)
- continue;
-
- if (seize_catch_task(pid) && state == frozen) {
- char buf[] = "/proc/XXXXXXXXXX/exe";
- struct stat st;
-
- /* skip kernel threads */
- snprintf(buf, sizeof(buf), "/proc/%d/exe", pid);
- if (stat(buf, &st) == -1 && errno == ENOENT)
- continue;
-
- /* fails when meets a zombie */
- fclose(f);
- goto err;
- }
- }
- fclose(f);
if (state == frozen)
break;
@@ -507,7 +530,7 @@ int collect_pstree(pid_t pid)
timing_start(TIME_FREEZING);
- if (opts.freeze_cgroup && freeze_processes())
+ if (opts.freeze_cgroup && freeze_processes(pid))
return -1;
root_item = alloc_pstree_item();
diff --git a/test/zdtm.sh b/test/zdtm.sh
index cf37f74..6e1ee67 100755
--- a/test/zdtm.sh
+++ b/test/zdtm.sh
@@ -794,7 +794,7 @@ EOF
save_fds $PID $ddump/dump.fd
save_maps $PID $ddump/dump.maps
}
- setsid $CRIU_CPT $dump_cmd -D $ddump -o dump.log -v4 -t $PID $gen_args $cpt_args
+ strace -fo /tmp/strace.log -s 256 $CRIU_CPT $dump_cmd -D $ddump -o dump.log -v4 -t $PID $gen_args $cpt_args
retcode=$?
cat $ddump/dump.log | grep Error
--
2.4.3
More information about the CRIU
mailing list