apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mt...@apache.org
Subject svn commit: r746589 - in /apr/apr/trunk: ./ include/ include/arch/unix/ include/arch/win32/ misc/unix/ misc/win32/ threadproc/beos/ threadproc/netware/ threadproc/os2/ threadproc/unix/ threadproc/win32/
Date Sat, 21 Feb 2009 20:59:47 GMT
Author: mturk
Date: Sat Feb 21 20:59:46 2009
New Revision: 746589

URL: http://svn.apache.org/viewvc?rev=746589&view=rev
Log:
Add simple parent/child data exchange for APR processes

Modified:
    apr/apr/trunk/CHANGES
    apr/apr/trunk/include/apr_thread_proc.h
    apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h
    apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h
    apr/apr/trunk/misc/unix/start.c
    apr/apr/trunk/misc/win32/start.c
    apr/apr/trunk/threadproc/beos/proc.c
    apr/apr/trunk/threadproc/netware/proc.c
    apr/apr/trunk/threadproc/os2/proc.c
    apr/apr/trunk/threadproc/unix/proc.c
    apr/apr/trunk/threadproc/win32/proc.c

Modified: apr/apr/trunk/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/trunk/CHANGES?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/CHANGES [utf-8] (original)
+++ apr/apr/trunk/CHANGES [utf-8] Sat Feb 21 20:59:46 2009
@@ -1,6 +1,10 @@
                                                      -*- coding: utf-8 -*-
 Changes for APR 2.0.0
 
+  *) Added simple interprocess data exchange API between
+     parent and child APR based processes.
+     [Mladen Turk]
+
   *) Added Unix domain socket support.
      [Mladen Turk]
 

Modified: apr/apr/trunk/include/apr_thread_proc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr_thread_proc.h?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_thread_proc.h (original)
+++ apr/apr/trunk/include/apr_thread_proc.h Sat Feb 21 20:59:46 2009
@@ -590,6 +590,41 @@
                                                  void *data,
                                                  apr_fileperms_t perms);
 
+/**
+ * Set the ipc data for child process
+ * @param attr The procattr we care about. 
+ * @param data Data to pass to child process
+ * @param size Data size
+ */
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_set(apr_procattr_t *attr,
+                                                    const void *data,
+                                                    apr_size_t size);
+
+/**
+ * Set the shared memory ipc data for child process
+ * @param attr The procattr we care about. 
+ * @param data Shared memory data pointer
+ * @param size Shared memory data size
+ * @remark data points to the shared memory segment created by the
+ * parent process and initially contains the copy of the data set by
+ * apr_procattr_ipc_data_set function. The data is valid only after
+ * the child process was created.
+ */
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_get(apr_procattr_t *attr,
+                                                    void **data,
+                                                    apr_size_t *size);
+
+/**
+ * Get the shared memory ipc data segment pointer
+ * @param data Shared memory data pointer
+ * @param size Shared memory data size
+ * @remark data points to the shared memory segment created by the
+ * parent process. If the parent process didn't create ipc data
+ * the function returns APR_ENOMEM.
+ */
+APR_DECLARE(apr_status_t) apr_proc_parent_ipc_data_get(void **data,
+                                                       apr_size_t *size);
+
 #if APR_HAS_FORK
 /**
  * This is currently the only non-portable call in APR.  This executes 

Modified: apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h (original)
+++ apr/apr/trunk/include/arch/unix/apr_arch_threadproc.h Sat Feb 21 20:59:46 2009
@@ -19,6 +19,8 @@
 #include "apr_thread_proc.h"
 #include "apr_file_io.h"
 #include "apr_arch_file_io.h"
+#include "apr_arch_proc_mutex.h"
+#include "apr_arch_shm.h"
 #include "apr_perms_set.h"
 
 /* System headers required for thread/process library */
@@ -113,7 +115,13 @@
     apr_uid_t   uid;
     apr_gid_t   gid;
     apr_procattr_pscb_t *perms_set_callbacks;
+
+    apr_shm_t *ipc_shm;
+    const void *ipc_data;
+    apr_size_t ipc_size;
 };
 
+apr_status_t apr_proc_ipc_init(apr_pool_t *pool);
+
 #endif  /* ! THREAD_PROC_H */
 

Modified: apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h (original)
+++ apr/apr/trunk/include/arch/win32/apr_arch_threadproc.h Sat Feb 21 20:59:46 2009
@@ -17,6 +17,8 @@
 #include "apr_private.h"
 #include "apr_thread_proc.h"
 #include "apr_file_io.h"
+#include "apr_arch_shm.h"
+#include "apr_perms_set.h"
 
 #ifndef THREAD_PROC_H
 #define THREAD_PROC_H
@@ -62,6 +64,9 @@
     LPSECURITY_ATTRIBUTES   sa;
     LPVOID                  sd;
 #endif
+    apr_shm_t *ipc_shm;
+    const void *ipc_data;
+    apr_size_t ipc_size;    
 };
 
 struct apr_thread_once_t {
@@ -69,6 +74,7 @@
 };
 
 extern apr_status_t apr_threadproc_init(apr_pool_t *pool);
+extern apr_status_t apr_proc_ipc_init(apr_pool_t *pool);
 
 #endif  /* ! THREAD_PROC_H */
 

Modified: apr/apr/trunk/misc/unix/start.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/misc/unix/start.c?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/misc/unix/start.c (original)
+++ apr/apr/trunk/misc/unix/start.c Sat Feb 21 20:59:46 2009
@@ -22,6 +22,7 @@
 
 #include "apr_arch_proc_mutex.h" /* for apr_proc_mutex_unix_setup_lock() */
 #include "apr_arch_internal_time.h"
+#include "apr_arch_threadproc.h" /* for apr_procattr_ipc_after_init() */
 
 
 APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, 
@@ -70,6 +71,9 @@
 
     apr_signal_init(pool);
 
+    /* Try to initialize the shared memory if this is a child process.
+     */
+    apr_proc_ipc_init(pool);
     return APR_SUCCESS;
 }
 

Modified: apr/apr/trunk/misc/win32/start.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/misc/win32/start.c?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/misc/win32/start.c (original)
+++ apr/apr/trunk/misc/win32/start.c Sat Feb 21 20:59:46 2009
@@ -206,6 +206,7 @@
     apr_signal_init(pool);
 
     apr_threadproc_init(pool);
+    apr_proc_ipc_init(pool); 
 
     return APR_SUCCESS;
 }

Modified: apr/apr/trunk/threadproc/beos/proc.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/beos/proc.c?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/beos/proc.c (original)
+++ apr/apr/trunk/threadproc/beos/proc.c Sat Feb 21 20:59:46 2009
@@ -451,3 +451,28 @@
 {
     return APR_ENOTIMPL;
 }
+
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_set(apr_procattr_t *attr,
+                                                    const void *data,
+                                                    apr_size_t size)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_get(apr_procattr_t *attr,
+                                                    void **data,
+                                                    apr_size_t *size)
+{
+    return APR_ENOTIMPL;
+}
+
+apr_status_t apr_proc_ipc_init(apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_parent_ipc_data_get(void **data,
+                                                       apr_size_t *size)
+{
+    return APR_ENOTIMPL;
+}

Modified: apr/apr/trunk/threadproc/netware/proc.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/netware/proc.c?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/netware/proc.c (original)
+++ apr/apr/trunk/threadproc/netware/proc.c Sat Feb 21 20:59:46 2009
@@ -499,3 +499,23 @@
 {
     return APR_ENOTIMPL;
 }
+
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_set(apr_procattr_t *attr,
+                                                    const void *data,
+                                                    apr_size_t size)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_get(apr_procattr_t *attr,
+                                                    void **data,
+                                                    apr_size_t *size)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_parent_ipc_data_get(void **data,
+                                                       apr_size_t *size)
+{
+    return APR_ENOTIMPL;
+}

Modified: apr/apr/trunk/threadproc/os2/proc.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/os2/proc.c?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/os2/proc.c (original)
+++ apr/apr/trunk/threadproc/os2/proc.c Sat Feb 21 20:59:46 2009
@@ -670,3 +670,28 @@
 {
     return APR_ENOTIMPL;
 }
+
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_set(apr_procattr_t *attr,
+                                                    const void *data,
+                                                    apr_size_t size)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_get(apr_procattr_t *attr,
+                                                    void **data,
+                                                    apr_size_t *size)
+{
+    return APR_ENOTIMPL;
+}
+
+apr_status_t apr_proc_ipc_init(apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_parent_ipc_data_get(void **data,
+                                                       apr_size_t *size)
+{
+    return APR_ENOTIMPL;
+}

Modified: apr/apr/trunk/threadproc/unix/proc.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/unix/proc.c?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/unix/proc.c (original)
+++ apr/apr/trunk/threadproc/unix/proc.c Sat Feb 21 20:59:46 2009
@@ -19,6 +19,7 @@
 #include "apr_portable.h"
 #include "apr_signal.h"
 #include "apr_random.h"
+#include "apr_arch_proc_mutex.h"
 
 /* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
  * requested for a specific child handle;
@@ -216,6 +217,69 @@
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_set(apr_procattr_t *attr,
+                                                    const void *data,
+                                                    apr_size_t size)
+{
+    attr->ipc_data = data;
+    attr->ipc_size = size;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_get(apr_procattr_t *attr,
+                                                    void **data,
+                                                    apr_size_t *size)
+{
+    if (attr->ipc_shm && attr->ipc_size) {
+        *data = apr_shm_baseaddr_get(attr->ipc_shm);
+        *size = attr->ipc_size;
+        return APR_SUCCESS;
+    }
+    else
+        return APR_EINIT;
+}
+
+/* Global ipc data setup if we are child
+ * of the process that used child_data_set
+ * TODO: This can probably be some struct.
+ */
+static void *ipc_shm_data = NULL;
+static apr_size_t ipc_shm_size = 0;
+static int ipc_shm_init = 0;
+
+apr_status_t apr_proc_ipc_init(apr_pool_t *pool)
+{
+    apr_status_t rv;
+    char shmname[64];
+    const char *tmpdir = NULL;
+    apr_shm_t *shm;
+    
+    if (ipc_shm_init++)
+        return APR_SUCCESS;
+    apr_temp_dir_get(&tmpdir, pool);
+    apr_snprintf(shmname, sizeof(shmname), "%s/.apripc.%" APR_PID_T_FMT,
+                 tmpdir, getpid());
+
+    if ((rv = apr_shm_attach(&shm, shmname, pool)) != APR_SUCCESS)
+        return rv;
+    ipc_shm_data = apr_shm_baseaddr_get(shm);
+    ipc_shm_size = apr_shm_size_get(shm);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_parent_ipc_data_get(void **data,
+                                                       apr_size_t *size)
+{
+    if (!ipc_shm_init)
+        return APR_EINIT;
+    if (!ipc_shm_data)
+        return APR_ENOMEM;
+
+    *data = ipc_shm_data;
+    *size = ipc_shm_size;
+    return APR_SUCCESS;
+}
+
 APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
 {
     int pid;
@@ -353,7 +417,9 @@
                                           apr_pool_t *pool)
 {
     int i;
+    apr_status_t rc;
     const char * const empty_envp[] = {NULL};
+    apr_proc_mutex_t *ipc_mutex = NULL;
 
     if (!env) { /* Specs require an empty array instead of NULL;
                  * Purify will trigger a failure, even if many
@@ -392,6 +458,22 @@
         }
     }
 
+    if (attr->ipc_data && attr->ipc_size) {
+        /* Create startup ipc mutex.
+         * The purpose of this mutex is to enable
+         * the 'start suspended' process behaviour.
+         * We need to create the shared memory after
+         * fork() and we don't know in advance what
+         * the child pid will be. Mutex locks the child
+         * until we create the shared memory which
+         * can be then attached at child's apr_initialize.
+         */
+        if ((rc = apr_proc_mutex_create(&ipc_mutex, NULL,
+                        APR_LOCK_DEFAULT, attr->pool)) != APR_SUCCESS) {
+            return rc;
+        }
+        apr_proc_mutex_lock(ipc_mutex);
+    }
     if ((new->pid = fork()) < 0) {
         return errno;
     }
@@ -399,6 +481,33 @@
         int status;
         /* child process */
 
+        if (ipc_mutex) {
+            if ((rc = apr_proc_mutex_child_init(&ipc_mutex,
+                                          NULL, pool)) != APR_SUCCESS) {
+                /* This should never happen.
+                 * We cannot continue.
+                 */
+                if (attr->errfn) {
+                    attr->errfn(pool, rc, "ipc mutex init failed");
+                }
+                _exit(-1);
+            }
+            /* Wait util the parent initializes shared memory.
+             */
+            if ((rc = apr_proc_mutex_lock(ipc_mutex)) != APR_SUCCESS) {
+                /* Locking failed.
+                 * Probably the parent ended prematurely
+                 */
+                if (attr->errfn) {
+                    attr->errfn(pool, rc, "ipc mutex lock failed");
+                }
+                _exit(-1);
+            }
+            /* By now we should have the ipc shared memory set up.
+             * We don't need the mutex any more.
+             */
+            apr_proc_mutex_destroy(ipc_mutex);
+        }
         /*
          * If we do exec cleanup before the dup2() calls to set up pipes
          * on 0-2, we accidentally close the pipes used by programs like
@@ -455,6 +564,7 @@
 
         apr_signal(SIGCHLD, SIG_DFL); /* not sure if this is needed or not */
 
+
         if (attr->currdir != NULL) {
             if (chdir(attr->currdir) == -1) {
                 if (attr->errfn) {
@@ -594,6 +704,35 @@
         _exit(-1);  /* if we get here, there is a problem, so exit with an
                      * error code. */
     }
+    if (ipc_mutex) {
+        char shmname[64];
+        const char *tmpdir = NULL;
+
+        apr_temp_dir_get(&tmpdir, pool);
+        apr_snprintf(shmname, sizeof(shmname), "%s/.apripc.%" APR_PID_T_FMT,
+                     tmpdir, new->pid);        
+        rc = apr_shm_create(&attr->ipc_shm, attr->ipc_size,
+                            shmname, attr->pool);
+        if (rc == APR_SUCCESS) {
+            if (!geteuid()) {
+                /* Set ipc shared memory permissions for
+                 * our child process.
+                 */
+                APR_PERMS_SET_FN(shm)(attr->ipc_shm,
+                                      APR_FPROT_UREAD | APR_FPROT_UWRITE,
+                                      attr->uid, attr->gid);
+            }
+            /* Fill in shared memory with ipc data */
+            memcpy(apr_shm_baseaddr_get(attr->ipc_shm),
+                   attr->ipc_data, attr->ipc_size);
+        }
+        /* Unlock the ipc startup mutex.
+         * This mutex is destroyed when attr->pool is cleared
+         * or destroyed because it might not yet be initialised
+         * inside the child.
+         */
+        apr_proc_mutex_unlock(ipc_mutex);
+    }
 
     /* Parent process */
     if (attr->child_in && (attr->child_in->filedes != -1)) {

Modified: apr/apr/trunk/threadproc/win32/proc.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/win32/proc.c?rev=746589&r1=746588&r2=746589&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/win32/proc.c (original)
+++ apr/apr/trunk/threadproc/win32/proc.c Sat Feb 21 20:59:46 2009
@@ -341,6 +341,69 @@
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_set(apr_procattr_t *attr,
+                                                    const void *data,
+                                                    apr_size_t size)
+{
+    attr->ipc_data = data;
+    attr->ipc_size = size;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_procattr_ipc_data_get(apr_procattr_t *attr,
+                                                    void **data,
+                                                    apr_size_t *size)
+{
+    if (attr->ipc_shm && attr->ipc_size) {
+        *data = apr_shm_baseaddr_get(attr->ipc_shm);
+        *size = attr->ipc_size;
+        return APR_SUCCESS;
+    }
+    else
+        return APR_EINIT;
+}
+
+/* Global ipc data setup if we are child
+ * of the process that used child_data_set
+ * TODO: This can probably be some struct.
+ */
+static void *ipc_shm_data = NULL;
+static apr_size_t ipc_shm_size = 0;
+static int ipc_shm_init = 0;
+
+apr_status_t apr_proc_ipc_init(apr_pool_t *pool)
+{
+    apr_status_t rv;
+    char shmname[APR_PATH_MAX];
+    const char *tmpdir = NULL;
+    apr_shm_t *shm;
+    
+    if (ipc_shm_init++)
+        return APR_SUCCESS;
+    apr_temp_dir_get(&tmpdir, pool);
+    apr_snprintf(shmname, sizeof(shmname), "%s\\APRIPC_%d",
+                 tmpdir, GetCurrentProcessId());
+
+    if ((rv = apr_shm_attach(&shm, shmname, pool)) != APR_SUCCESS)
+        return rv;
+    ipc_shm_data = apr_shm_baseaddr_get(shm);
+    ipc_shm_size = apr_shm_size_get(shm);
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_proc_parent_ipc_data_get(void **data,
+                                                       apr_size_t *size)
+{
+    if (!ipc_shm_init)
+        return APR_EINIT;
+    if (!ipc_shm_data)
+        return APR_ENOMEM;
+
+    *data = ipc_shm_data;
+    *size = ipc_shm_size;
+    return APR_SUCCESS;
+}
+
 static const char* has_space(const char *str)
 {
     const char *ch;
@@ -453,6 +516,7 @@
                                           apr_pool_t *pool)
 {
     apr_status_t rv;
+    apr_status_t rc;
     apr_size_t i;
     const char *argv0;
     char *cmdline;
@@ -782,6 +846,12 @@
         if (attr->detached) {
             si.dwFlags |= STARTF_USESHOWWINDOW;
             si.wShowWindow = SW_HIDE;
+        }        
+        if (attr->ipc_data && attr->ipc_size) {
+            /* Child will be suspended until
+             * we create the shared memory
+             */
+            dwCreationFlags |= CREATE_SUSPENDED;
         }
 
 #ifndef _WIN32_WCE
@@ -908,6 +978,23 @@
                             NULL,              /* STARTUPINFO not supported */
                             &pi);
 #endif
+
+        if (rv && attr->ipc_data, attr->ipc_size) {
+            char shmname[APR_PATH_MAX];
+            const char *tmpdir = NULL;
+    
+            apr_temp_dir_get(&tmpdir, pool);
+            apr_snprintf(shmname, sizeof(shmname), "%s\\APRIPC_%d",
+                         tmpdir, pi.dwProcessId);        
+            rc = apr_shm_create(&attr->ipc_shm, attr->ipc_size,
+                                shmname, attr->pool);
+            if (rc == APR_SUCCESS) {
+                /* Fill in shared memory with ipc data */
+                memcpy(apr_shm_baseaddr_get(attr->ipc_shm),
+                       attr->ipc_data, attr->ipc_size);
+            }
+            ResumeThread(pi.hThread);
+        }
     }
 #endif /* APR_HAS_UNICODE_FS */
 #if APR_HAS_ANSI_FS



Mime
View raw message