Commit 7fe2bee8 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

seize: detach from external processes before killing dumped processes (v2)

When we kill a container, all processes from its pidns are killed by
SIGKILL, but we don't expect that someone from the freezer cgroup will
be killed too if it was not dumped.

(00.468446) Error (seize.c:439): Unexpected child 79162
(00.468489) Error (seize.c:440): BUG at seize.c:440

This situation is posiable, if someone enters into pidns by setns.

In this patch, we deatches from extra processes before killing dumped
processes. In this case, we are not get signals if someone is killed.

v2: use process_to_wait insread of adding a new var

https://jira.sw.ru/browse/PSBM-43795Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 0ce60fdb
...@@ -50,9 +50,6 @@ int unseize_task(pid_t pid, int orig_st, int st) ...@@ -50,9 +50,6 @@ int unseize_task(pid_t pid, int orig_st, int st)
} else } else
pr_err("Unknown final state %d\n", st); pr_err("Unknown final state %d\n", st);
if (opts.freeze_cgroup)
return 0;
if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) { if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) {
pr_perror("Unable to detach from %d", pid); pr_perror("Unable to detach from %d", pid);
return -1; return -1;
......
...@@ -176,6 +176,7 @@ static int seize_cgroup_tree(char *root_path, const char *state) ...@@ -176,6 +176,7 @@ static int seize_cgroup_tree(char *root_path, const char *state)
/* A number of tasks in a freezer cgroup which are not going to be dumped */ /* A number of tasks in a freezer cgroup which are not going to be dumped */
int processes_to_wait; int processes_to_wait;
static pid_t *processes_to_wait_pids;
/* /*
* A freezer cgroup can contain tasks which will not be dumped * A freezer cgroup can contain tasks which will not be dumped
...@@ -185,6 +186,10 @@ static int freezer_wait_processes() ...@@ -185,6 +186,10 @@ static int freezer_wait_processes()
{ {
int i; int i;
processes_to_wait_pids = xmalloc(sizeof(pid_t) * processes_to_wait);
if (processes_to_wait_pids == NULL)
return -1;
for (i = 0; i < processes_to_wait; i++) { for (i = 0; i < processes_to_wait; i++) {
int status; int status;
pid_t pid; pid_t pid;
...@@ -197,9 +202,12 @@ static int freezer_wait_processes() ...@@ -197,9 +202,12 @@ static int freezer_wait_processes()
pid = waitpid(-1, &status, 0); pid = waitpid(-1, &status, 0);
if (pid < 0) { if (pid < 0) {
pr_perror("Unable to wait processes"); pr_perror("Unable to wait processes");
xfree(processes_to_wait_pids);
return -1; return -1;
} }
pr_warn("Unexpected process %d in the freezer cgroup (status 0x%x)\n", pid, status); pr_warn("Unexpected process %d in the freezer cgroup (status 0x%x)\n", pid, status);
processes_to_wait_pids[i] = pid;
} }
return 0; return 0;
...@@ -207,27 +215,29 @@ static int freezer_wait_processes() ...@@ -207,27 +215,29 @@ static int freezer_wait_processes()
static int freezer_detach(void) static int freezer_detach(void)
{ {
char path[PATH_MAX]; int i;
FILE *f;
if (!opts.freeze_cgroup) if (!opts.freeze_cgroup)
return 0; return 0;
snprintf(path, sizeof(path), "%s/tasks", opts.freeze_cgroup); for (i = 0; i < processes_to_wait; i++) {
f = fopen(path, "r"); pid_t pid = processes_to_wait_pids[i];
if (f == NULL) { int status, save_errno;
pr_perror("Unable to open %s", path);
return -1;
}
while (fgets(path, sizeof(path), f)) {
pid_t pid;
pid = atoi(path); if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == 0)
continue;
save_errno = errno;
if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) /* A process may be killed by SIGKILL */
pr_perror("Unable to detach from %d", pid); if (wait4(pid, &status, __WALL, NULL) == pid) {
pr_warn("The %d process returned 0x %x\n", pid, status);
continue;
}
errno = save_errno;
pr_perror("Unable to detach from %d", pid);
} }
fclose(f);
return 0; return 0;
} }
...@@ -402,7 +412,7 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st) ...@@ -402,7 +412,7 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st)
unseize_task(item->pid.real, item->state, st); unseize_task(item->pid.real, item->state, st);
if (st == TASK_DEAD || opts.freeze_cgroup) if (st == TASK_DEAD)
return; return;
for (i = 1; i < item->nr_threads; i++) for (i = 1; i < item->nr_threads; i++)
...@@ -448,10 +458,6 @@ void pstree_switch_state(struct pstree_item *root_item, int st) ...@@ -448,10 +458,6 @@ void pstree_switch_state(struct pstree_item *root_item, int st)
if (st != TASK_DEAD) if (st != TASK_DEAD)
freezer_restore_state(); freezer_restore_state();
pr_info("Unfreezing tasks into %d\n", st);
for_each_pstree_item(item)
unseize_task_and_threads(item, st);
/* /*
* We need to detach from all processes before waiting the init * We need to detach from all processes before waiting the init
* process, because one of these processes may collect processes from a * process, because one of these processes may collect processes from a
...@@ -460,6 +466,10 @@ void pstree_switch_state(struct pstree_item *root_item, int st) ...@@ -460,6 +466,10 @@ void pstree_switch_state(struct pstree_item *root_item, int st)
*/ */
freezer_detach(); freezer_detach();
pr_info("Unfreezing tasks into %d\n", st);
for_each_pstree_item(item)
unseize_task_and_threads(item, st);
if (st == TASK_DEAD) if (st == TASK_DEAD)
pstree_wait(root_item); pstree_wait(root_item);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment