[CRIU] [PATCH 3/5] compel: Make struct seize_task_status be possible to be extensible
Kirill Tkhai
ktkhai at virtuozzo.com
Sat Apr 15 10:15:55 PDT 2017
Sometimes get_status() callback in compel_wait_task()
may want to collect additional fields, e.g. NSpid and
friends. When compel_wait_task() goes to the second
turn to try_again, such fields must be freed, because
we're going to call get_status() once again, and it
rewrites the previous collected data.
So, allow get_status() to collect what it wants, and
also allow struct seize_task_status to be extensible:
on an extension of this structure users may safely
recompile their programs without any code changes.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
compel/include/uapi/infect.h | 2 ++
compel/src/lib/infect.c | 24 +++++++++++++++++++++---
criu/seize.c | 8 +++++++-
3 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/compel/include/uapi/infect.h b/compel/include/uapi/infect.h
index da0ca3a69..1e744c62a 100644
--- a/compel/include/uapi/infect.h
+++ b/compel/include/uapi/infect.h
@@ -21,11 +21,13 @@ struct seize_task_status {
unsigned long long sigpnd;
unsigned long long shdpnd;
int seccomp_mode;
+ /* Add new members to the bottom and do not change existing */
};
extern int compel_wait_task(int pid, int ppid,
int (*get_status)(int pid, struct seize_task_status *),
struct seize_task_status *st);
+extern void compel_consume_seize_task_status(struct seize_task_status *ss);
extern int compel_stop_task(int pid);
extern int compel_resume_task(pid_t pid, int orig_state, int state);
diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c
index 7f6d2f3f1..e0aaf7720 100644
--- a/compel/src/lib/infect.c
+++ b/compel/src/lib/infect.c
@@ -102,12 +102,15 @@ static int parse_pid_status(int pid, struct seize_task_status *ss)
int compel_stop_task(int pid)
{
- int ret;
struct seize_task_status ss;
+ int ret;
ret = compel_interrupt_task(pid);
- if (ret == 0)
+ if (ret == 0) {
ret = compel_wait_task(pid, -1, parse_pid_status, &ss);
+ if (ret != -1)
+ compel_consume_seize_task_status(&ss);
+ }
return ret;
}
@@ -184,6 +187,17 @@ static int skip_sigstop(int pid, int nr_signals)
return 0;
}
+/* Init dynamically allocated fields in NULL and do not touch other */
+static void init_seize_task_status(struct seize_task_status *ss)
+{
+}
+
+/* Free dynamically allocated fields in compel_wait_task() and do not touch other */
+void compel_consume_seize_task_status(struct seize_task_status *ss)
+{
+ init_seize_task_status(ss);
+}
+
/*
* This routine seizes task putting it into a special
* state where we can manipulate the task via ptrace
@@ -207,6 +221,7 @@ int compel_wait_task(int pid, int ppid,
*/
try_again:
+ init_seize_task_status(ss);
ret = wait4(pid, &status, __WALL, NULL);
if (ret < 0) {
@@ -231,7 +246,7 @@ int compel_wait_task(int pid, int ppid,
else
pr_err("Unseizable non-zombie %d found, state %c, err %d/%d\n",
pid, ss->state, ret, wait_errno);
- return -1;
+ goto err_free;
}
if (ret < 0)
@@ -271,6 +286,7 @@ int compel_wait_task(int pid, int ppid,
}
ret = 0;
+ compel_consume_seize_task_status(ss);
goto try_again;
}
@@ -304,6 +320,8 @@ int compel_wait_task(int pid, int ppid,
err:
if (ptrace(PTRACE_DETACH, pid, NULL, NULL))
pr_perror("Unable to detach from %d", pid);
+err_free:
+ compel_consume_seize_task_status(ss);
return -1;
}
diff --git a/criu/seize.c b/criu/seize.c
index 5727b8ff8..718880679 100644
--- a/criu/seize.c
+++ b/criu/seize.c
@@ -518,6 +518,7 @@ static int collect_children(struct pstree_item *item)
/* Here is a recursive call (Depth-first search) */
ret = collect_task(c);
+ compel_consume_seize_task_status(&creds->s);
if (ret < 0)
goto free;
}
@@ -742,15 +743,19 @@ static int collect_threads(struct pstree_item *item)
if (ret == TASK_DEAD) {
pr_err("Zombie thread not supported\n");
+ compel_consume_seize_task_status(&t_creds.s);
goto err;
}
- if (!creds_dumpable(dmpi(item)->pi_creds, &t_creds))
+ if (!creds_dumpable(dmpi(item)->pi_creds, &t_creds)) {
+ compel_consume_seize_task_status(&t_creds.s);
goto err;
+ }
if (ret == TASK_STOPPED) {
nr_stopped++;
}
+ compel_consume_seize_task_status(&t_creds.s);
}
if (nr_stopped && nr_stopped != nr_inprogress) {
@@ -871,6 +876,7 @@ int collect_pstree(void)
dmpi(root_item)->pi_creds = creds;
ret = collect_task(root_item);
+ compel_consume_seize_task_status(&creds->s);
if (ret < 0)
goto err;
More information about the CRIU
mailing list