[Devel] [PATCH 2/4] restart thread safety: remove malloc from ckpt_fork_child
Oren Laadan
orenl at cs.columbia.edu
Fri Jul 30 10:08:31 PDT 2010
We use clone and eclone directly and not through glibc, therefore
must explicitly care about thread-safety of malloc.
This patch eliminates the use of malloc() from ckpt_fork_child(). The
malloc was needed to make a pid-array for eclone using data from the
vpids from the checkpoint image. In particular, it added the 0th level
pid. Instead, we re-package vpids array early on by expanding the array
and pre-adding 0th pids before any of the forks take place.
Signed-off-by: Oren Laadan <orenl at cs.columbia.edu>
---
restart.c | 82 ++++++++++++++++++++++++++++++++----------------------------
1 files changed, 44 insertions(+), 38 deletions(-)
diff --git a/restart.c b/restart.c
index b281ca2..b274e37 100644
--- a/restart.c
+++ b/restart.c
@@ -1725,9 +1725,9 @@ static pid_t ckpt_fork_child(struct ckpt_ctx *ctx, struct task *child)
unsigned long flags = SIGCHLD;
pid_t pid = 0;
pid_t *pids = &pid;
- int i, j, depth;
+ int i, depth;
- ckpt_dbg("forking child vpid %d flags %#x\n", child->pid, child->flags);
+ ckpt_dbg("fork child vpid %d flags %#x\n", child->pid, child->flags);
stk = genstack_alloc(PTHREAD_STACK_MIN);
if (!stk) {
@@ -1747,17 +1747,7 @@ static pid_t ckpt_fork_child(struct ckpt_ctx *ctx, struct task *child)
depth = child->piddepth + 1;
clone_args.nr_pids = depth;
- pids = malloc(sizeof(pid_t) * depth);
- if (!pids) {
- perror("ckpt_fork_child pids malloc");
- return -1;
- }
-
- memset(pids, 0, sizeof(pid_t) * depth);
- pids[0] = child->pid;
-
- for (i = child->piddepth - 1, j = 0; i >= 0; i--, j++)
- pids[j + 1] = ctx->vpids_arr[child->vidx + j];
+ pids = &ctx->vpids_arr[child->vidx];
#ifndef CLONE_NEWPID
if (child->piddepth > child->creator->piddepth) {
@@ -1810,9 +1800,6 @@ static pid_t ckpt_fork_child(struct ckpt_ctx *ctx, struct task *child)
if (pid < 0 || !(child->flags & TASK_THREAD))
genstack_release(stk);
- if (pids != &pid)
- free(pids);
-
ckpt_dbg("forked child vpid %d (asked %d)\n", pid, child->pid);
return pid;
}
@@ -2336,34 +2323,53 @@ static int ckpt_read_tree(struct ckpt_ctx *ctx)
return ret;
}
-/* set the vpids pointers in all the tasks */
+/*
+ * transform vpids arrays to the format convenient for eclone:
+ * prefix the level 0 pid to every sequence of nested pids.
+ * also, set the vpids pointers in all the tasks.
+ */
static int assign_vpids(struct ckpt_ctx *ctx)
{
- int d, hidx, tidx;
- struct task *t;
+ __s32 *vpids_arr;
+ int depth, hidx, vidx, tidx;
+ struct task *task;
- for (hidx = 0, tidx = 0; tidx < ctx->pids_nr; tidx++) {
- t = &ctx->tasks_arr[tidx];
- d = t->piddepth = ctx->pids_arr[tidx].depth;
- if (!d) {
- ckpt_dbg("task[%d].vidx = -1\n", tidx);
- t->vidx = -1;
- continue;
- }
- t->vidx = hidx;
+ vpids_arr = malloc(sizeof(__s32) * (ctx->vpids_nr + ctx->pids_nr));
+ if (vpids_arr == NULL) {
+ perror("assign_vpids malloc");
+ return -1;
+ }
+
+ for (tidx = 0, hidx = 0, vidx = 0; tidx < ctx->pids_nr; tidx++) {
+ task = &ctx->tasks_arr[tidx];
+ depth = ctx->pids_arr[tidx].depth;
+
+ task->vidx = vidx;
+ task->piddepth = depth;
+
+ /* set task's and top level pid */
+ vpids_arr[vidx++] = task->pid;
+ /* copy task's nested pids */
+ memcpy(&vpids_arr[vidx], &ctx->vpids_arr[hidx],
+ sizeof(__s32) * depth);
+
+ vidx += depth;
+ hidx += depth;
+
+#ifdef CHECKPOINT_DEBUG
ckpt_dbg("task[%d].vidx = %d (depth %d, rpid %d)\n",
- tidx, hidx, t->piddepth, ctx->pids_arr[tidx].vpid);
- int i;
- for (i=0; i<t->piddepth; i++)
- ckpt_dbg("task[%d].vpid[%d] = %d\n", tidx, i,
- ctx->vpids_arr[hidx+i]);
- hidx += d;
- if (hidx > ctx->vpids_nr) {
- ckpt_err("Error parsing vpids array");
- return -1;
+ tidx, vidx, depth, ctx->pids_arr[tidx].vpid);
+ while (depth-- > 0) {
+ ckpt_dbg("task[%d].vpid[%d] = %d\n", tidx,
+ depth, vpids_arr[hidx - depth - 1]);
}
+#endif
}
+ /* relpace "raw" vpids_arr with this one */
+ free(ctx->vpids_arr);
+ ctx->vpids_arr = vpids_arr;
+
return 0;
}
--
1.7.0.4
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers
More information about the Devel
mailing list