Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib Push the fiddly tasks for exec and fork from rumphijack ...



details:   https://anonhg.NetBSD.org/src/rev/48b9f8593f31
branches:  trunk
changeset: 762130:48b9f8593f31
user:      pooka <pooka%NetBSD.org@localhost>
date:      Wed Feb 16 15:33:46 2011 +0000

description:
Push the fiddly tasks for exec and fork from rumphijack to rumpclient.
This makes it possible easily execute those operations also from
non-hijacked rump clients (plus fixes one memory leak in an error
branch).

diffstat:

 lib/librumpclient/rumpclient.c |  74 +++++++++++++++++++++++++++--------------
 lib/librumpclient/rumpclient.h |   6 ++-
 lib/librumphijack/hijack.c     |  60 +++++++++++++--------------------
 3 files changed, 77 insertions(+), 63 deletions(-)

diffs (265 lines):

diff -r 5a2d3a036c68 -r 48b9f8593f31 lib/librumpclient/rumpclient.c
--- a/lib/librumpclient/rumpclient.c    Wed Feb 16 13:15:49 2011 +0000
+++ b/lib/librumpclient/rumpclient.c    Wed Feb 16 15:33:46 2011 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpclient.c,v 1.29 2011/02/15 10:37:07 pooka Exp $   */
+/*      $NetBSD: rumpclient.c,v 1.30 2011/02/16 15:33:47 pooka Exp $   */
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -74,6 +74,8 @@
 int    (*host_kevent)(int, const struct kevent *, size_t,
                       struct kevent *, size_t, const struct timespec *);
 
+int    (*host_execve)(const char *, char *const[], char *const[]);
+
 #include "sp_common.c"
 
 static struct spclient clispc = {
@@ -748,6 +750,7 @@
        FINDSYM(setsockopt);
        FINDSYM(dup);
        FINDSYM(kqueue);
+       FINDSYM(execve);
 #if !__NetBSD_Prereq__(5,99,7)
        FINDSYM(kevent);
 #else
@@ -813,7 +816,7 @@
        pthread_sigmask(SIG_SETMASK, &fullset, &omask);
        rpf = malloc(sizeof(*rpf));
        if (rpf == NULL)
-               return NULL;
+               goto out;
 
        if ((rv = prefork_req(&clispc, &omask, &resp)) != 0) {
                free(rpf);
@@ -926,6 +929,30 @@
        return 0;
 }
 
+pid_t
+rumpclient_fork(pid_t (*forkfn)(void))
+{
+       struct rumpclient_fork *rf;
+       pid_t rv;
+
+       if ((rf = rumpclient_prefork()) == NULL)
+               return -1;
+                
+       switch ((rv = forkfn())) {
+       case -1:
+               /* XXX: cancel rf */
+               break;
+       case 0:
+               if (rumpclient_fork_init(rf) == -1)
+                       rv = -1;
+               break;
+       default:
+               break;
+       }
+
+       return rv;
+}
+
 /*
  * Process is about to exec.  Save info about our existing connection
  * in the env.  rumpclient will check for this info in init().
@@ -933,13 +960,13 @@
  * may use it as well.
  */
 int
-rumpclient__exec_augmentenv(char *const oenv1[], char *const oenv2[],
-       char ***newenvp)
+rumpclient_exec(const char *path, char *const argv[], char *const envp[])
 {
        char buf[4096];
        char **newenv;
        char *envstr, *envstr2;
-       size_t nelem1, nelem2;
+       size_t nelem;
+       int rv, sverrno;
 
        snprintf(buf, sizeof(buf), "RUMPCLIENT__EXECFD=%d,%d",
            clispc.spc_fd, kq);
@@ -963,31 +990,28 @@
                envstr2 = NULL;
        }
 
-       nelem1 = 0;
-       if (oenv1) {
-               for (; oenv1[nelem1]; nelem1++)
-                       continue;
-       }
-       nelem2 = 0;
-       if (oenv2) {
-               for (; oenv2[nelem2]; nelem2++)
-                       continue;
-       }
+       for (nelem = 0; envp && envp[nelem]; nelem++)
+               continue;
 
-       newenv = malloc(sizeof(*newenv) * nelem1+nelem2+3);
+       newenv = malloc(sizeof(*newenv) * nelem+3);
        if (newenv == NULL) {
                free(envstr2);
                free(envstr);
                return ENOMEM;
        }
-       memcpy(&newenv[0], oenv1, sizeof(*oenv1) * nelem1);
-       memcpy(&newenv[nelem1], oenv2, sizeof(*oenv2) * nelem2);
+       memcpy(&newenv[0], envp, nelem*sizeof(*envp));
+
+       newenv[nelem] = envstr;
+       newenv[nelem+1] = envstr2;
+       newenv[nelem+2] = NULL;
+
+       rv = host_execve(path, argv, newenv);
 
-       newenv[nelem1+nelem2] = envstr;
-       newenv[nelem1+nelem2+1] = envstr2;
-       newenv[nelem1+nelem2+2] = NULL;
-
-       *newenvp = newenv;
-
-       return 0;
+       _DIAGASSERT(rv != 0);
+       sverrno = errno;
+       free(envstr2);
+       free(envstr);
+       free(newenv);
+       errno = sverrno;
+       return rv;
 }
diff -r 5a2d3a036c68 -r 48b9f8593f31 lib/librumpclient/rumpclient.h
--- a/lib/librumpclient/rumpclient.h    Wed Feb 16 13:15:49 2011 +0000
+++ b/lib/librumpclient/rumpclient.h    Wed Feb 16 15:33:46 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rumpclient.h,v 1.6 2011/02/14 14:56:23 pooka Exp $     */
+/*     $NetBSD: rumpclient.h,v 1.7 2011/02/16 15:33:47 pooka Exp $     */
 
 /*-
  * Copyright (c) 2010 Antti Kantee.  All Rights Reserved.
@@ -39,6 +39,9 @@
 struct rumpclient_fork *rumpclient_prefork(void);
 int                    rumpclient_fork_init(struct rumpclient_fork *);
 
+int rumpclient_fork(pid_t (*forkfn)(void));
+int rumpclient_exec(const char *, char *const [], char *const[]);
+
 #define RUMPCLIENT_RETRYCONN_INFTIME ((time_t)-1)
 #define RUMPCLIENT_RETRYCONN_ONCE ((time_t)-2)
 #define RUMPCLIENT_RETRYCONN_DIE ((time_t)-3)
@@ -50,7 +53,6 @@
        RUMPCLIENT_CLOSE_FCLOSEM
 };
 int rumpclient__closenotify(int *, enum rumpclient_closevariant);
-int rumpclient__exec_augmentenv(char *const[], char *const[], char ***);
 
 __END_DECLS
 
diff -r 5a2d3a036c68 -r 48b9f8593f31 lib/librumphijack/hijack.c
--- a/lib/librumphijack/hijack.c        Wed Feb 16 13:15:49 2011 +0000
+++ b/lib/librumphijack/hijack.c        Wed Feb 16 15:33:46 2011 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: hijack.c,v 1.41 2011/02/15 14:01:52 pooka Exp $       */
+/*      $NetBSD: hijack.c,v 1.42 2011/02/16 15:33:46 pooka Exp $       */
 
 /*-
  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.41 2011/02/15 14:01:52 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.42 2011/02/16 15:33:46 pooka Exp $");
 
 #define __ssp_weak_name(fun) _hijack_ ## fun
 
@@ -594,33 +594,14 @@
        return dodup(oldd, 0);
 }
 
-/*
- * We just wrap fork the appropriate rump client calls to preserve
- * the file descriptors of the forked parent in the child, but
- * prevent double use of connection fd.
- */
 pid_t
 fork()
 {
-       struct rumpclient_fork *rf;
        pid_t rv;
 
        DPRINTF(("fork\n"));
 
-       if ((rf = rumpclient_prefork()) == NULL)
-               return -1;
-
-       switch ((rv = host_fork())) {
-       case -1:
-               /* XXX: cancel rf */
-               break;
-       case 0:
-               if (rumpclient_fork_init(rf) == -1)
-                       rv = -1;
-               break;
-       default:
-               break;
-       }
+       rv = rumpclient_fork(host_fork);
 
        DPRINTF(("fork returns %d\n", rv));
        return rv;
@@ -644,31 +625,38 @@
 }
 
 int
-execve(const char *path, char *const argv[], char *const oenvp[])
+execve(const char *path, char *const argv[], char *const envp[])
 {
        char buf[128];
-       char **env;
-       char *dup2maskenv[2];
        char *dup2str;
-       int rv;
+       char **newenv;
+       size_t nelem;
+       int rv, sverrno;
 
        snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2MASK=%u", dup2mask);
        dup2str = malloc(strlen(buf)+1);
        if (dup2str == NULL)
                return ENOMEM;
        strcpy(dup2str, buf);
-       dup2maskenv[0] = dup2str;
-       dup2maskenv[1] = NULL;
 
-       rv = rumpclient__exec_augmentenv(oenvp, dup2maskenv, &env);
-       if (rv)
-               return rv;
+       for (nelem = 0; envp && envp[nelem]; nelem++)
+               continue;
+       newenv = malloc(sizeof(*newenv) * nelem+2);
+       if (newenv == NULL) {
+               free(dup2str);
+               return ENOMEM;
+       }
+       memcpy(newenv, envp, nelem*sizeof(*newenv));
+       newenv[nelem] = dup2str;
+       newenv[nelem+1] = NULL;
 
-       rv = host_execve(path, argv, env);
-       if (rv != 0) {
-               free(dup2str);
-               free(env); /* XXX missing some strings within env */
-       }
+       rv = rumpclient_exec(path, argv, newenv);
+
+       _DIAGASSERT(rv != 0);
+       sverrno = errno;
+       free(newenv);
+       free(dup2str);
+       errno = sverrno;
        return rv;
 }
 



Home | Main Index | Thread Index | Old Index