diff options
author | Yuriy Vasiliev <yuriy.vasiliev@openvz.org> | 2022-01-20 19:13:59 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@gmail.com> | 2022-07-02 19:06:30 +0300 |
commit | 7968e71db86f92b09a207bb580924265892fe8ec (patch) | |
tree | 1b4bf3f79677c1392a7d4544d7bb5dddec379788 /criu | |
parent | 029ca223767f41ab8aeee6441c04aba3f3e5765b (diff) |
infect: add SIGTSTP support
Add SIGTSTP signal dump and restore. Add a corresponding field
in the image, save it only if a task is in the stopped state.
Restore task state by sending desired stop signal if it is present
in the image. Fallback to SIGSTOP if it's absent.
Signed-off-by: Yuriy Vasiliev <yuriy.vasiliev@openvz.org>
Diffstat (limited to 'criu')
-rw-r--r-- | criu/cr-dump.c | 5 | ||||
-rw-r--r-- | criu/cr-restore.c | 11 | ||||
-rw-r--r-- | criu/include/pid.h | 4 | ||||
-rw-r--r-- | criu/proc_parse.c | 15 | ||||
-rw-r--r-- | criu/pstree.c | 1 | ||||
-rw-r--r-- | criu/seize.c | 8 |
6 files changed, 40 insertions, 4 deletions
diff --git a/criu/cr-dump.c b/criu/cr-dump.c index 60e90baed..e60da88ed 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -781,6 +781,11 @@ static int dump_task_core_all(struct parasite_ctl *ctl, struct pstree_item *item core->thread_core->creds->lsm_profile = dmpi(item)->thread_lsms[0]->profile; core->thread_core->creds->lsm_sockcreate = dmpi(item)->thread_lsms[0]->sockcreate; + if (core->tc->task_state == TASK_STOPPED) { + core->tc->has_stop_signo = true; + core->tc->stop_signo = item->pid->stop_signo; + } + ret = parasite_dump_thread_leader_seized(ctl, pid, core); if (ret) goto err; diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 398faf048..279246c19 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1350,6 +1350,9 @@ static inline int fork_with_pid(struct pstree_item *item) item->pid->state = ca.core->tc->task_state; rsti(item)->cg_set = ca.core->tc->cg_set; + if (ca.core->tc->has_stop_signo) + item->pid->stop_signo = ca.core->tc->stop_signo; + if (item->pid->state != TASK_DEAD && !task_alive(item)) { pr_err("Unknown task state %d\n", item->pid->state); return -1; @@ -2104,8 +2107,14 @@ static void finalize_restore(void) xfree(ctl); - if ((item->pid->state == TASK_STOPPED) || (opts.final_state == TASK_STOPPED)) + if (opts.final_state == TASK_STOPPED) kill(item->pid->real, SIGSTOP); + else if (item->pid->state == TASK_STOPPED) { + if (item->pid->stop_signo > 0) + kill(item->pid->real, item->pid->stop_signo); + else + kill(item->pid->real, SIGSTOP); + } } } diff --git a/criu/include/pid.h b/criu/include/pid.h index 49cb2d322..b2b7a361a 100644 --- a/criu/include/pid.h +++ b/criu/include/pid.h @@ -31,6 +31,10 @@ struct pid { pid_t real; int state; /* TASK_XXX constants */ + /* If an item is in stopped state it has a signal number + * that caused task to stop. + */ + int stop_signo; /* * The @virt pid is one which used in the image itself and keeps diff --git a/criu/proc_parse.c b/criu/proc_parse.c index 6b41a81db..946b0fc40 100644 --- a/criu/proc_parse.c +++ b/criu/proc_parse.c @@ -1027,12 +1027,13 @@ int parse_pid_status(pid_t pid, struct seize_task_status *ss, void *data) cr->s.sigpnd = 0; cr->s.shdpnd = 0; + cr->s.sigblk = 0; cr->s.seccomp_mode = SECCOMP_MODE_DISABLED; if (bfdopenr(&f)) return -1; - while (done < 13) { + while (done < 14) { str = breadline(&f); if (str == NULL) break; @@ -1146,10 +1147,20 @@ int parse_pid_status(pid_t pid, struct seize_task_status *ss, void *data) done++; continue; } + if (!strncmp(str, "SigBlk:", 7)) { + unsigned long long sigblk = 0; + + if (sscanf(str + 7, "%llx", &sigblk) != 1) + goto err_parse; + cr->s.sigblk |= sigblk; + + done++; + continue; + } } /* seccomp and nspids are optional */ - expected_done = (parsed_seccomp ? 11 : 10); + expected_done = (parsed_seccomp ? 12 : 11); if (kdat.has_nspid) expected_done++; if (done == expected_done) diff --git a/criu/pstree.c b/criu/pstree.c index f4d77b3a4..72c4a3502 100644 --- a/criu/pstree.c +++ b/criu/pstree.c @@ -222,6 +222,7 @@ struct pstree_item *__alloc_pstree_item(bool rst) item->pid->ns[0].virt = -1; item->pid->real = -1; item->pid->state = TASK_UNDEF; + item->pid->stop_signo = -1; item->born_sid = -1; item->pid->item = item; futex_init(&item->task_st); diff --git a/criu/seize.c b/criu/seize.c index 58564ca74..1333d6db9 100644 --- a/criu/seize.c +++ b/criu/seize.c @@ -615,6 +615,9 @@ static int collect_children(struct pstree_item *item) else processes_to_wait--; + if (ret == TASK_STOPPED) + c->pid->stop_signo = compel_parse_stop_signo(pid); + c->pid->real = pid; c->parent = item; c->pid->state = ret; @@ -646,7 +649,7 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st) * the item->state is the state task was in when we seized one. */ - compel_resume_task(item->pid->real, item->pid->state, st); + compel_resume_task_sig(item->pid->real, item->pid->state, st, item->pid->stop_signo); if (st == TASK_DEAD) return; @@ -950,6 +953,9 @@ int collect_pstree(void) else processes_to_wait--; + if (ret == TASK_STOPPED) + root_item->pid->stop_signo = compel_parse_stop_signo(pid); + pr_info("Seized task %d, state %d\n", pid, ret); root_item->pid->state = ret; |