aboutsummaryrefslogtreecommitdiffstats
path: root/ports
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@windriver.com>2011-10-26 18:49:00 -0500
committerPeter Seebach <peter.seebach@windriver.com>2011-11-02 13:31:43 -0500
commit375c6ad5af75703a638d557f50f173ee9b035302 (patch)
tree90ff90f002865ae8f9998945e44e7cfeb1cbc5b9 /ports
parent6177474388f243c9ff783da074a531ef8fd173fd (diff)
downloadpseudo-375c6ad5af75703a638d557f50f173ee9b035302.tar.gz
pseudo-375c6ad5af75703a638d557f50f173ee9b035302.tar.bz2
pseudo-375c6ad5af75703a638d557f50f173ee9b035302.zip
Rework the clone wrapper to add an intermediate function to resolve a defect.
Previously the clone(2) wrapper unconditionallity restored the system environment. It also invokes the checks to see if the user has requested pseudo to be disabled or unloaded. Due to the semantics of clone, this caused both the parent and child processes to be disabled or unloaded. The new code adds an intermediate function, wrap_clone_child, that only runs within the child context. This way we can be sure to only disable/unload pseudo from within the child process. In addition, we avoid mucking with the environment if CLONE_VM is set, since this will affect both parent and child. Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
Diffstat (limited to 'ports')
-rw-r--r--ports/linux/newclone/guts/clone.c27
-rw-r--r--ports/linux/newclone/pseudo_wrappers.c33
-rw-r--r--ports/linux/oldclone/guts/clone.c27
-rw-r--r--ports/linux/oldclone/pseudo_wrappers.c36
4 files changed, 89 insertions, 34 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"
diff --git a/ports/linux/oldclone/guts/clone.c b/ports/linux/oldclone/guts/clone.c
index e8b87e8..5240bb3 100644
--- a/ports/linux/oldclone/guts/clone.c
+++ b/ports/linux/oldclone/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);
+ rc = (*real_clone)(wrap_clone_child, child_stack, flags, myargs, pid);
+
+ /* 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/oldclone/pseudo_wrappers.c b/ports/linux/oldclone/pseudo_wrappers.c
index f0bf112..c0ce5dd 100644
--- a/ports/linux/oldclone/pseudo_wrappers.c
+++ b/ports/linux/oldclone/pseudo_wrappers.c
@@ -1,13 +1,40 @@
-int
+static int
wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg) {
/* unused */
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;
- va_list ap;
pid_t *pid;
struct user_desc *tls;
pid_t *ctid;
@@ -30,11 +57,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"