[CRIU] [PATCH RESEND v1 15/55] pid: Alloc threads dynamically
Kirill Tkhai
ktkhai at virtuozzo.com
Fri Mar 24 08:11:24 PDT 2017
Threads pid values also may be multi-level, so allocate
them dynamically.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/cr-dump.c | 10 +++++-----
criu/cr-restore.c | 14 +++++++-------
criu/files-reg.c | 4 ++--
criu/include/proc_parse.h | 2 +-
criu/include/pstree.h | 2 +-
criu/parasite-syscall.c | 2 +-
criu/proc_parse.c | 23 ++++++++++++++++-------
criu/pstree.c | 23 +++++++++++++----------
criu/seize.c | 32 ++++++++++++++++++++++----------
9 files changed, 68 insertions(+), 44 deletions(-)
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index c61bb263..018c61d1 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -821,7 +821,7 @@ static int collect_file_locks(void)
static int dump_task_thread(struct parasite_ctl *parasite_ctl,
const struct pstree_item *item, int id)
{
- struct pid *tid = &item->threads[id];
+ struct pid *tid = item->threads[id];
CoreEntry *core = item->core[id];
pid_t pid = tid->real;
int ret = -1;
@@ -963,9 +963,9 @@ static int dump_task_signals(pid_t pid, struct pstree_item *item)
/* Dump private signals for each thread */
for (i = 0; i < item->nr_threads; i++) {
- ret = dump_signal_queue(item->threads[i].real, &item->core[i]->thread_core->signals_p, false);
+ ret = dump_signal_queue(item->threads[i]->real, &item->core[i]->thread_core->signals_p, false);
if (ret) {
- pr_err("Can't dump private signals for thread %d\n", item->threads[i].real);
+ pr_err("Can't dump private signals for thread %d\n", item->threads[i]->real);
return -1;
}
}
@@ -989,8 +989,8 @@ static int dump_task_threads(struct parasite_ctl *parasite_ctl,
for (i = 0; i < item->nr_threads; i++) {
/* Leader is already dumped */
- if (item->pid->real == item->threads[i].real) {
- item->threads[i].ns[0].virt = vpid(item);
+ if (item->pid->real == item->threads[i]->real) {
+ item->threads[i]->ns[0].virt = vpid(item);
continue;
}
if (dump_task_thread(parasite_ctl, item, i))
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index a1c20fc3..f3af65cd 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -578,7 +578,7 @@ static int open_cores(int pid, CoreEntry *leader_core)
goto err;
for (i = 0; i < current->nr_threads; i++) {
- tpid = current->threads[i].ns[0].virt;
+ tpid = current->threads[i]->ns[0].virt;
if (tpid == pid)
cores[i] = leader_core;
@@ -1571,7 +1571,7 @@ static int attach_to_tasks(bool root_seized)
return -1;
for (i = 0; i < item->nr_threads; i++) {
- pid_t pid = item->threads[i].real;
+ pid_t pid = item->threads[i]->real;
if (item != root_item || !root_seized || i != 0) {
if (ptrace(PTRACE_SEIZE, pid, 0, 0)) {
@@ -1624,7 +1624,7 @@ static int catch_tasks(bool root_seized, enum trace_flags *flag)
return -1;
for (i = 0; i < item->nr_threads; i++) {
- pid_t pid = item->threads[i].real;
+ pid_t pid = item->threads[i]->real;
if (ptrace(PTRACE_INTERRUPT, pid, 0, 0)) {
pr_perror("Can't interrupt the %d task", pid);
@@ -1658,7 +1658,7 @@ static int clear_breakpoints()
if (!task_alive(item))
continue;
for (i = 0; i < item->nr_threads; i++)
- ret |= ptrace_flush_breakpoints(item->threads[i].real);
+ ret |= ptrace_flush_breakpoints(item->threads[i]->real);
}
return ret;
@@ -1702,7 +1702,7 @@ static void finalize_restore_detach(int status)
continue;
for (i = 0; i < item->nr_threads; i++) {
- pid = item->threads[i].real;
+ pid = item->threads[i]->real;
if (pid < 0) {
BUG_ON(status >= 0);
break;
@@ -2727,7 +2727,7 @@ static int prepare_signals(int pid, struct task_restore_args *ta, CoreEntry *lea
for (i = 0; i < current->nr_threads; i++) {
if (!current->core[i]->thread_core->signals_p)/*backward compatibility*/
ret = open_signal_image(CR_FD_PSIGNAL,
- current->threads[i].ns[0].virt, &siginfo_priv_nr[i]);
+ current->threads[i]->ns[0].virt, &siginfo_priv_nr[i]);
else
ret = prepare_one_signal_queue(current->core[i]->thread_core->signals_p,
&siginfo_priv_nr[i]);
@@ -3186,7 +3186,7 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
struct rt_sigframe *sigframe;
k_rtsigset_t *blkset = NULL;
- thread_args[i].pid = current->threads[i].ns[0].virt;
+ thread_args[i].pid = current->threads[i]->ns[0].virt;
thread_args[i].siginfo_n = siginfo_priv_nr[i];
thread_args[i].siginfo = task_args->siginfo;
thread_args[i].siginfo += siginfo_n;
diff --git a/criu/files-reg.c b/criu/files-reg.c
index ede2744e..48f068d2 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -824,8 +824,8 @@ int dead_pid_conflict(void)
* process, this is handled during restore.
*/
item = node->item;
- if (item->pid->real == item->threads[i].real ||
- item->threads[i].ns[0].virt != pid)
+ if (item->pid->real == item->threads[i]->real ||
+ item->threads[i]->ns[0].virt != pid)
continue;
}
diff --git a/criu/include/proc_parse.h b/criu/include/proc_parse.h
index d67ac5e5..13b71092 100644
--- a/criu/include/proc_parse.h
+++ b/criu/include/proc_parse.h
@@ -101,7 +101,7 @@ extern int parse_file_locks(void);
extern int get_fd_mntid(int fd, int *mnt_id);
struct pid;
-extern int parse_threads(int pid, struct pid **_t, int *_n);
+extern int parse_threads(int pid, struct pid ***_t, int *_n);
int parse_children(pid_t pid, pid_t **_c, int *_n);
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index 6edd04d7..0a62bfde 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -22,7 +22,7 @@ struct pstree_item {
pid_t born_sid;
int nr_threads; /* number of threads */
- struct pid *threads; /* array of threads */
+ struct pid **threads; /* array of threads */
CoreEntry **core;
TaskKobjIdsEntry *ids;
union {
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index 5d59e6e8..d28652f1 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -481,7 +481,7 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
struct infect_ctx *ictx;
unsigned long p;
- BUG_ON(item->threads[0].real != pid);
+ BUG_ON(item->threads[0]->real != pid);
p = get_exec_start(vma_area_list);
if (!p) {
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index 5e9780a4..84a8f9ea 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -2196,11 +2196,11 @@ int parse_posix_timers(pid_t pid, struct proc_posix_timers_stat *args)
goto out;
}
-int parse_threads(int pid, struct pid **_t, int *_n)
+int parse_threads(int pid, struct pid ***_t, int *_n)
{
struct dirent *de;
DIR *dir;
- struct pid *t = NULL;
+ struct pid **t = NULL;
int nr = 1;
if (*_t)
@@ -2211,23 +2211,32 @@ int parse_threads(int pid, struct pid **_t, int *_n)
return -1;
while ((de = readdir(dir))) {
- struct pid *tmp;
+ struct pid **tmp;
/* We expect numbers only here */
if (de->d_name[0] == '.')
continue;
if (*_t == NULL) {
- tmp = xrealloc(t, nr * sizeof(struct pid));
+ tmp = xrealloc(t, nr * sizeof(struct pid *));
if (!tmp) {
+ while (--nr > 0)
+ xfree(t[nr-1]);
xfree(t);
return -1;
}
t = tmp;
- t[nr - 1].ns[0].virt = -1;
+ t[nr - 1] = xmalloc(sizeof(struct pid));
+ if (!t[nr - 1]) {
+ while (--nr > 0)
+ xfree(t[nr-1]);
+ xfree(t);
+ }
+ t[nr - 1]->ns[0].virt = -1;
}
- t[nr - 1].real = atoi(de->d_name);
- t[nr - 1].state = TASK_THREAD;
+ t[nr - 1]->real = atoi(de->d_name);
+ t[nr - 1]->state = TASK_THREAD;
+ t[nr - 1]->level = 1;
nr++;
}
diff --git a/criu/pstree.c b/criu/pstree.c
index 0dffabcf..46c2096b 100644
--- a/criu/pstree.c
+++ b/criu/pstree.c
@@ -149,7 +149,7 @@ int pstree_alloc_cores(struct pstree_item *item)
return -1;
for (i = 0; i < item->nr_threads; i++) {
- if (item->threads[i].real == item->pid->real)
+ if (item->threads[i]->real == item->pid->real)
item->core[i] = core_entry_alloc(1, 1);
else
item->core[i] = core_entry_alloc(1, 0);
@@ -336,7 +336,7 @@ int dump_pstree(struct pstree_item *root_item)
goto err;
for (i = 0; i < item->nr_threads; i++)
- e.threads[i] = item->threads[i].ns[0].virt;
+ e.threads[i] = item->threads[i]->ns[0].virt;
ret = pb_write_one(img, &e, PB_PSTREE);
xfree(e.threads);
@@ -602,23 +602,26 @@ static int read_pstree_image(pid_t *pid_max)
}
pi->nr_threads = e->n_threads;
- pi->threads = xmalloc(e->n_threads * sizeof(struct pid));
+ pi->threads = xzalloc(e->n_threads * sizeof(struct pid *));
if (!pi->threads)
break;
for (i = 0; i < e->n_threads; i++) {
struct pid *node;
- pi->threads[i].real = -1;
- pi->threads[i].level = pi->pid->level;
- pi->threads[i].ns[0].virt = e->threads[i];
- pi->threads[i].state = TASK_THREAD;
- pi->threads[i].item = NULL;
+ pi->threads[i] = xmalloc(sizeof(struct pid) + (pi->pid->level-1) * sizeof(node->ns[0]));
+ if (!pi->threads)
+ goto err;
+ pi->threads[i]->real = -1;
+ pi->threads[i]->level = pi->pid->level;
+ pi->threads[i]->ns[0].virt = e->threads[i];
+ pi->threads[i]->state = TASK_THREAD;
+ pi->threads[i]->item = NULL;
if (i == 0)
continue; /* A thread leader is in a tree already */
- node = lookup_create_pid(pi->threads[i].ns[0].virt, &pi->threads[i]);
+ node = lookup_create_pid(pi->threads[i]->ns[0].virt, pi->threads[i]);
BUG_ON(node == NULL);
- if (node != &pi->threads[i]) {
+ if (node != pi->threads[i]) {
pr_err("Unexpected task %d in a tree %d\n", e->threads[i], i);
return -1;
}
diff --git a/criu/seize.c b/criu/seize.c
index d5079ca6..7e44d136 100644
--- a/criu/seize.c
+++ b/criu/seize.c
@@ -544,8 +544,8 @@ static void unseize_task_and_threads(const struct pstree_item *item, int st)
return;
for (i = 1; i < item->nr_threads; i++)
- if (ptrace(PTRACE_DETACH, item->threads[i].real, NULL, NULL))
- pr_perror("Unable to detach from %d", item->threads[i].real);
+ if (ptrace(PTRACE_DETACH, item->threads[i]->real, NULL, NULL))
+ pr_perror("Unable to detach from %d", item->threads[i]->real);
}
static void pstree_wait(struct pstree_item *root_item)
@@ -620,7 +620,7 @@ static inline bool thread_collected(struct pstree_item *i, pid_t tid)
return true;
for (t = 0; t < i->nr_threads; t++)
- if (tid == i->threads[t].real)
+ if (tid == i->threads[t]->real)
return true;
return false;
@@ -677,7 +677,7 @@ static bool creds_dumpable(struct proc_status_creds *parent,
static int collect_threads(struct pstree_item *item)
{
- struct pid *threads = NULL;
+ struct pid **threads = NULL;
int nr_threads = 0, i = 0, ret, nr_inprogress, nr_stopped = 0;
ret = parse_threads(item->pid->real, &threads, &nr_threads);
@@ -690,19 +690,23 @@ static int collect_threads(struct pstree_item *item)
}
/* The number of threads can't be less than already frozen */
- item->threads = xrealloc(item->threads, nr_threads * sizeof(struct pid));
+ item->threads = xrealloc(item->threads, nr_threads * sizeof(struct pid *));
if (item->threads == NULL)
return -1;
if (item->nr_threads == 0) {
- item->threads[0].real = item->pid->real;
+ item->threads[0] = xmalloc(sizeof(struct pid));
+ if (!item->threads[0])
+ return -1;
+ item->threads[0]->real = item->pid->real;
item->nr_threads = 1;
- item->threads[0].item = NULL;
+ item->threads[0]->item = NULL;
+ item->threads[0]->level = 1;
}
nr_inprogress = 0;
for (i = 0; i < nr_threads; i++) {
- pid_t pid = threads[i].real;
+ pid_t pid = threads[i]->real;
struct proc_status_creds t_creds = {};
if (thread_collected(item, pid))
@@ -734,8 +738,12 @@ static int collect_threads(struct pstree_item *item)
processes_to_wait--;
BUG_ON(item->nr_threads + 1 > nr_threads);
- item->threads[item->nr_threads].real = pid;
- item->threads[item->nr_threads].item = NULL;
+ item->threads[item->nr_threads] = xmalloc(sizeof(struct pid));
+ if (!item->threads[item->nr_threads])
+ goto err;
+ item->threads[item->nr_threads]->real = pid;
+ item->threads[item->nr_threads]->item = NULL;
+ item->threads[item->nr_threads]->level = 1;
item->nr_threads++;
if (ret == TASK_DEAD) {
@@ -756,10 +764,14 @@ static int collect_threads(struct pstree_item *item)
goto err;
}
+ while (nr_threads-- > 0)
+ xfree(threads[nr_threads]);
xfree(threads);
return nr_inprogress;
err:
+ while (nr_threads-- > 0)
+ xfree(threads[nr_threads]);
xfree(threads);
return -1;
}
More information about the CRIU
mailing list