aboutsummaryrefslogtreecommitdiffstats
path: root/ports/linux/newclone
diff options
context:
space:
mode:
Diffstat (limited to 'ports/linux/newclone')
-rw-r--r--ports/linux/newclone/guts/clone.c27
-rw-r--r--ports/linux/newclone/pseudo_wrappers.c33
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"