diff options
Diffstat (limited to 'ports/linux/newclone')
-rw-r--r-- | ports/linux/newclone/guts/clone.c | 27 | ||||
-rw-r--r-- | ports/linux/newclone/pseudo_wrappers.c | 33 |
2 files changed, 44 insertions, 16 deletions
diff --git a/ports/linux/newclone/guts/clone.c b/ports/linux/newclone/guts/clone.c index 4b65036..ee6fc09 100644 --- a/ports/linux/newclone/guts/clone.c +++ b/ports/linux/newclone/guts/clone.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2010 Wind River Systems; see + * Copyright (c) 2008-2011 Wind River Systems; see * guts/COPYRIGHT for information. * * static int @@ -8,18 +8,23 @@ */ /* because clone() doesn't actually continue in this function, we * can't check the return and fix up environment variables in the - * child. Instead, we have to temporarily do any fixup, then possibly - * undo it later. UGH! + * child. Instead, we have to create an intermediate function, + * wrap_clone_child, which does this fix up. */ - pseudo_debug(1, "client resetting for clone(2) call\n"); - pseudo_setupenv(); - if (!pseudo_get_value("PSEUDO_UNLOAD")) { - pseudo_reinit_libpseudo(); - } else { - pseudo_dropenv(); - } + + struct clone_args * myargs = malloc(sizeof(struct clone_args)); + + myargs->fn = fn; + myargs->flags = flags; + myargs->arg = arg; + /* call the real syscall */ - rc = (*real_clone)(fn, child_stack, flags, arg, pid, tls, ctid); + rc = (*real_clone)(wrap_clone_child, child_stack, flags, myargs, pid, tls, ctid); + + /* If we're not sharing memory, we need to free myargs in the parent */ + if (!(flags & CLONE_VM)) + free(myargs); + /* ... * return rc; * } diff --git a/ports/linux/newclone/pseudo_wrappers.c b/ports/linux/newclone/pseudo_wrappers.c index dd44408..9dbac42 100644 --- a/ports/linux/newclone/pseudo_wrappers.c +++ b/ports/linux/newclone/pseudo_wrappers.c @@ -10,6 +10,34 @@ ap) { return 0; } +struct clone_args { + int (*fn)(void *); + int flags; + void *arg; +}; + +int wrap_clone_child(void *args) { + struct clone_args *clargs = args; + + int (*fn)(void *) = clargs->fn; + int flags = clargs->flags; + void *arg = clargs->arg; + + /* We always free in the client */ + free(clargs); + + if (!(flags & CLONE_VM)) { + pseudo_setupenv(); + if (!pseudo_get_value("PSEUDO_UNLOAD")) { + pseudo_reinit_libpseudo(); + } else { + pseudo_dropenv(); + } + } + + return fn(arg); +} + int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) { sigset_t saved; @@ -42,11 +70,6 @@ clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...) { int save_errno; int save_disabled = pseudo_disabled; - /* because clone() doesn't actually continue in this function, we - * can't check the return and fix up environment variables in the - * child. Instead, we have to temporarily do any fixup, then possibly - * undo it later. UGH! - */ #include "guts/clone.c" |