]> granicus.if.org Git - apache/commitdiff
Basic support for spawning children porcesses via fork() and killing them with kill().
authorPaul Querna <pquerna@apache.org>
Thu, 30 Oct 2008 10:46:58 +0000 (10:46 +0000)
committerPaul Querna <pquerna@apache.org>
Thu, 30 Oct 2008 10:46:58 +0000 (10:46 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@709136 13f79535-47bb-0310-9956-ffa450edef68

server/mpm/simple/simple_children.c
server/mpm/simple/simple_core.c
server/mpm/simple/simple_run.c
server/mpm/simple/simple_types.h

index cf09d21ff9900a8e4a1757525e07d400c2b4ba23..bfa1a7657ecdb5351333582a98c1727c41bd3d19 100644 (file)
 #include "simple_types.h"
 #include "simple_event.h"
 #include "simple_run.h"
+#include "http_log.h"
 #include "simple_children.h"
 #include "apr_hash.h"
 
+#include <unistd.h> /* For fork() */
+
 #define SPAWN_CHILDREN_INTERVAL (apr_time_from_sec(5))
 
 static void simple_kill_random_child(simple_core_t * sc)
 {
-    apr_thread_mutex_lock(sc->mtx);
     /* See comment in simple_spawn_child for why we check here. */
     if (!sc->run_single_process) {
+        apr_hash_index_t *hi;
+        simple_child_t *child = NULL;
+
+        apr_thread_mutex_lock(sc->mtx);
+        hi = apr_hash_first(sc->pool, sc->children);
+        if (hi != NULL) {
+            apr_hash_this(hi, NULL, NULL, (void **)&child); 
+            apr_hash_set(sc->children, &child->pid, sizeof(child->pid), NULL);
+        }
+        apr_thread_mutex_unlock(sc->mtx);
+        
+        if (child != NULL) {
+            kill(child->pid, 9);
+            /* TODO: recycle child object */
+        }
     }
-    apr_thread_mutex_unlock(sc->mtx);
 }
 
-static void simple_spawn_child(simple_core_t * sc)
+static void clean_child_exit(int code) __attribute__ ((noreturn));
+static void clean_child_exit(int code)
+{
+    /* TODO: Pool cleanups.... sigh. */
+    exit(code);
+}
+
+static int simple_spawn_child(simple_core_t * sc)
 {
-    apr_thread_mutex_lock(sc->mtx);
+    pid_t pid = 0;
+    int rv = 0;
     /* Although we could cut this off 'earlier', and not even invoke this 
      * function, I would like to keep the functions invoked when in debug mode
      * to be as close as possible to those when not in debug... So, we just skip
      * the actual spawn itself, but go through all of the motions...
      */
     if (!sc->run_single_process) {
+        if (sc->spawn_via == SIMPLE_SPAWN_FORK) {
+            
+            pid = fork();
+            if (pid == -1) {
+                rv = errno;
+                ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
+                             "simple_spawn_child: Unable to fork new process");
+                return rv;
+            }
+            
+            if (pid == 0) {
+                /* this is the child process */
+                
+                rv = simple_child_loop(sc);
 
+                if (rv) {
+                    clean_child_exit(APEXIT_CHILDFATAL);
+                }
+                else {
+                    clean_child_exit(0);
+                }
+            }
+        }
+        else {
+            /* TODO: SIMPLE_SPAWN_EXEC */
+            abort();
+        }
+    }
+
+    if (pid != 0) {
+        simple_child_t *child;
+
+        apr_thread_mutex_lock(sc->mtx);
+
+        child = apr_palloc(sc->pool, sizeof(simple_child_t));
+        child->pid = pid;
+        apr_hash_set(sc->children, &child->pid, sizeof(child->pid), child);
+
+        apr_thread_mutex_unlock(sc->mtx);
     }
-    apr_thread_mutex_unlock(sc->mtx);
+    
+    return 0;
 }
 
 void simple_check_children_size(simple_core_t * sc, void *baton)
@@ -83,10 +146,11 @@ void simple_check_children_size(simple_core_t * sc, void *baton)
         }
     }
     else if (count < wanted) {
+        int rv = 0;
         /* spawn some kids */
         int to_spawn = wanted - count;
-        for (i = 0; i < to_spawn; i++) {
-            simple_spawn_child(sc);
+        for (i = 0; rv == 0 && i < to_spawn; i++) {
+            rv = simple_spawn_child(sc);
         }
     }
     else {
index 391bd42433a8c0276580990b4e1a7723ea42a1af..3e4f228a79e2e9f7b4c5ae44ae1c52f599e35e14 100644 (file)
@@ -49,6 +49,8 @@ apr_status_t simple_core_init(simple_core_t * sc, apr_pool_t * pool)
     sc->procmgr.max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
 
     sc->children = apr_hash_make(sc->pool);
+    /* TODO: configurable spawning mech */
+    sc->spawn_via = SIMPLE_SPAWN_FORK;
 
     APR_RING_INIT(&sc->timer_ring, simple_timer_t, link);
     APR_RING_INIT(&sc->dead_timer_ring, simple_timer_t, link);
index 0256173a6cf14aef5953e0ee855c957adb82e332..691c27523a3643e76e031b3cba5282c3ab6363f1 100644 (file)
@@ -138,6 +138,7 @@ static void *simple_timer_invoke(apr_thread_t * thread, void *baton)
     ep->cb(sc, ep->baton);
 
     apr_thread_mutex_lock(sc->mtx);
+    APR_RING_ELEM_INIT(ep, link);
     APR_RING_INSERT_TAIL(&sc->dead_timer_ring, ep, simple_timer_t, link);
     apr_thread_mutex_unlock(sc->mtx);
 
index 6061391d5d67577c8e95e33edea24efd95d297ee..f88d6028c4b1394c579b58e5b21e0df57d274b34 100644 (file)
@@ -35,11 +35,6 @@ typedef struct
     int max_requests_per_child;
 } simple_proc_mgr_t;
 
-typedef struct
-{
-    int pid;
-} simple_child_t;
-
 typedef void (*simple_timer_cb) (simple_core_t * sc, void *baton);
 typedef void (*simple_io_sock_cb) (simple_core_t * sc, apr_socket_t * sock,
                                    int flags, void *baton);
@@ -56,6 +51,12 @@ typedef enum
     SIMPLE_PT_USER
 } simple_poll_type_e;
 
+typedef enum
+{
+    SIMPLE_SPAWN_FORK,
+    SIMPLE_SPAWN_EXEC,
+} simple_spawn_type_e;
+
 struct simple_sb_t
 {
     simple_poll_type_e type;
@@ -71,6 +72,13 @@ struct simple_timer_t
     void *baton;
 };
 
+typedef struct simple_child_t simple_child_t;
+struct simple_child_t
+{
+    /* TODO: More is needed here. */
+    pid_t pid;
+};
+
 struct simple_core_t
 {
     apr_pool_t *pool;
@@ -81,6 +89,7 @@ struct simple_core_t
 
     int run_single_process;
     int run_foreground;
+    simple_spawn_type_e spawn_via;
 
     simple_proc_mgr_t procmgr;