Commit 75d3f1a2 authored by Paul Querna's avatar Paul Querna
Browse files

Basic support for spawning children porcesses via fork() and killing them with kill().


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@709136 13f79535-47bb-0310-9956-ffa450edef68
parent 9bb7da87
Loading
Loading
Loading
Loading
+69 −5
Changes for server/mpm/simple/simple_children.c: 69 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -19,34 +19,97 @@
#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 */
        }
    }
}

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)
{
    apr_thread_mutex_lock(sc->mtx);
    /* TODO: Pool cleanups.... sigh. */
    exit(code);
}

static int simple_spawn_child(simple_core_t * sc)
{
    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);
    }
    
    return 0;
}

void simple_check_children_size(simple_core_t * sc, void *baton)
{
    unsigned int count;
@@ -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 {
+2 −0
Changes for server/mpm/simple/simple_core.c: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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);
+1 −0
Changes for server/mpm/simple/simple_run.c: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -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);

+14 −5
Changes for server/mpm/simple/simple_types.h: 14 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -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;