diff options
Diffstat (limited to 'server/mpm/mpmt_os2/mpmt_os2.c')
-rw-r--r-- | server/mpm/mpmt_os2/mpmt_os2.c | 615 |
1 files changed, 0 insertions, 615 deletions
diff --git a/server/mpm/mpmt_os2/mpmt_os2.c b/server/mpm/mpmt_os2/mpmt_os2.c deleted file mode 100644 index 84addf8e69..0000000000 --- a/server/mpm/mpmt_os2/mpmt_os2.c +++ /dev/null @@ -1,615 +0,0 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2000-2002 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. - * - * Portions of this software are based upon public domain software - * originally written at the National Center for Supercomputing Applications, - * University of Illinois, Urbana-Champaign. - */ - -/* Multi-process, multi-threaded MPM for OS/2 - * - * Server consists of - * - a main, parent process - * - a small, static number of child processes - * - * The parent process's job is to manage the child processes. This involves - * spawning children as required to ensure there are always ap_daemons_to_start - * processes accepting connections. - * - * Each child process consists of a a pool of worker threads and a - * main thread that accepts connections & passes them to the workers via - * a work queue. The worker thread pool is dynamic, managed by a maintanence - * thread so that the number of idle threads is kept between - * min_spare_threads & max_spare_threads. - * - */ - -/* - Todo list - - Enforce MaxClients somehow -*/ -#define CORE_PRIVATE -#define INCL_NOPMAPI -#define INCL_DOS -#define INCL_DOSERRORS - -#include "ap_config.h" -#include "httpd.h" -#include "mpm_default.h" -#include "http_main.h" -#include "http_log.h" -#include "http_config.h" -#include "http_core.h" /* for get_remote_host */ -#include "http_connection.h" -#include "mpm.h" -#include "ap_mpm.h" -#include "ap_listen.h" -#include "apr_portable.h" -#include "mpm_common.h" -#include "apr_strings.h" -#include <os2.h> -#include <process.h> - -/* We don't need many processes, - * they're only for redundancy in the event of a crash - */ -#define HARD_SERVER_LIMIT 10 - -/* Limit on the total number of threads per process - */ -#ifndef HARD_THREAD_LIMIT -#define HARD_THREAD_LIMIT 256 -#endif - -server_rec *ap_server_conf; -static apr_pool_t *pconf = NULL; /* Pool for config stuff */ -static const char *ap_pid_fname=NULL; - -/* Config globals */ -static int one_process = 0; -static int ap_daemons_to_start = 0; -static int ap_thread_limit = 0; -static int ap_max_requests_per_child = 0; -int ap_min_spare_threads = 0; -int ap_max_spare_threads = 0; - -/* Keep track of a few interesting statistics */ -int ap_max_daemons_limit = -1; - -/* volatile just in case */ -static int volatile shutdown_pending; -static int volatile restart_pending; -static int volatile is_graceful = 0; -ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard */ -static int is_parent_process=TRUE; -HMTX ap_mpm_accept_mutex = 0; - -/* An array of these is stored in a shared memory area for passing - * sockets from the parent to child processes - */ -typedef struct { - struct sockaddr_in name; - apr_os_sock_t listen_fd; -} listen_socket_t; - -typedef struct { - HMTX accept_mutex; - listen_socket_t listeners[1]; -} parent_info_t; - -static char master_main(); -static void spawn_child(int slot); -void ap_mpm_child_main(apr_pool_t *pconf); -static void set_signals(); - - -int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s ) -{ - char *listener_shm_name; - parent_info_t *parent_info; - ULONG rc; - pconf = _pconf; - ap_server_conf = s; - restart_pending = 0; - - DosSetMaxFH(ap_thread_limit * 2); - listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getppid()); - rc = DosGetNamedSharedMem((PPVOID)&parent_info, listener_shm_name, PAG_READ); - is_parent_process = rc != 0; - ap_scoreboard_fname = apr_psprintf(pconf, "/sharemem/httpd/scoreboard.%d", is_parent_process ? getpid() : getppid()); - - if (rc == 0) { - /* Child process */ - ap_listen_rec *lr; - int num_listeners = 0; - - ap_mpm_accept_mutex = parent_info->accept_mutex; - - /* Set up a default listener if necessary */ - if (ap_listeners == NULL) { - ap_listen_rec *lr = apr_pcalloc(s->process->pool, sizeof(ap_listen_rec)); - ap_listeners = lr; - apr_sockaddr_info_get(&lr->bind_addr, "0.0.0.0", APR_UNSPEC, - DEFAULT_HTTP_PORT, 0, s->process->pool); - apr_socket_create(&lr->sd, lr->bind_addr->family, - SOCK_STREAM, s->process->pool); - } - - for (lr = ap_listeners; lr; lr = lr->next) { - apr_sockaddr_t *sa; - apr_os_sock_put(&lr->sd, &parent_info->listeners[num_listeners].listen_fd, pconf); - apr_socket_addr_get(&sa, APR_LOCAL, lr->sd); - num_listeners++; - } - - DosFreeMem(parent_info); - - /* Do the work */ - ap_mpm_child_main(pconf); - - /* Outta here */ - return 1; - } - else { - /* Parent process */ - char restart; - is_parent_process = TRUE; - - if (ap_setup_listeners(ap_server_conf) < 1) { - ap_log_error(APLOG_MARK, APLOG_ALERT, 0, s, - "no listening sockets available, shutting down"); - return 1; - } - - ap_log_pid(pconf, ap_pid_fname); - - restart = master_main(); - ++ap_my_generation; - ap_scoreboard_image->global->running_generation = ap_my_generation; - - if (!restart) { - const char *pidfile = ap_server_root_relative(pconf, ap_pid_fname); - - if (pidfile != NULL && remove(pidfile) == 0) { - ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, - ap_server_conf, "removed PID file %s (pid=%d)", - pidfile, getpid()); - } - - ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, - "caught SIGTERM, shutting down"); - return 1; - } - } /* Parent process */ - - return 0; /* Restart */ -} - - - -/* Main processing of the parent process - * returns TRUE if restarting - */ -static char master_main() -{ - server_rec *s = ap_server_conf; - ap_listen_rec *lr; - parent_info_t *parent_info; - char *listener_shm_name; - int listener_num, num_listeners, slot; - ULONG rc; - - printf("%s \n", ap_get_server_version()); - set_signals(); - - if (ap_setup_listeners(ap_server_conf) < 1) { - ap_log_error(APLOG_MARK, APLOG_ALERT, 0, s, - "no listening sockets available, shutting down"); - return FALSE; - } - - /* Allocate a shared memory block for the array of listeners */ - for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) { - num_listeners++; - } - - listener_shm_name = apr_psprintf(pconf, "/sharemem/httpd/parent_info.%d", getpid()); - rc = DosAllocSharedMem((PPVOID)&parent_info, listener_shm_name, - sizeof(parent_info_t) + num_listeners * sizeof(listen_socket_t), - PAG_READ|PAG_WRITE|PAG_COMMIT); - - if (rc) { - ap_log_error(APLOG_MARK, APLOG_ALERT, APR_FROM_OS_ERROR(rc), s, - "failure allocating shared memory, shutting down"); - return FALSE; - } - - /* Store the listener sockets in the shared memory area for our children to see */ - for (listener_num = 0, lr = ap_listeners; lr; lr = lr->next, listener_num++) { - apr_os_sock_get(&parent_info->listeners[listener_num].listen_fd, lr->sd); - } - - /* Create mutex to prevent multiple child processes from detecting - * a connection with apr_poll() - */ - - rc = DosCreateMutexSem(NULL, &ap_mpm_accept_mutex, DC_SEM_SHARED, FALSE); - - if (rc) { - ap_log_error(APLOG_MARK, APLOG_ALERT, APR_FROM_OS_ERROR(rc), s, - "failure creating accept mutex, shutting down"); - return FALSE; - } - - parent_info->accept_mutex = ap_mpm_accept_mutex; - - /* Allocate shared memory for scoreboard */ - if (ap_scoreboard_image == NULL) { - void *sb_mem; - rc = DosAllocSharedMem(&sb_mem, ap_scoreboard_fname, - ap_calc_scoreboard_size(), - PAG_COMMIT|PAG_READ|PAG_WRITE); - - if (rc) { - ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf, - "unable to allocate shared memory for scoreboard , exiting"); - return FALSE; - } - - ap_init_scoreboard(sb_mem); - } - - ap_scoreboard_image->global->restart_time = apr_time_now(); - ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, - "%s configured -- resuming normal operations", - ap_get_server_version()); - ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, - "Server built: %s", ap_get_server_built()); -#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, - "AcceptMutex: %s (default: %s)", - apr_proc_mutex_name(accept_mutex), - apr_proc_mutex_defname()); -#endif - if (one_process) { - ap_scoreboard_image->parent[0].pid = getpid(); - ap_mpm_child_main(pconf); - return FALSE; - } - - while (!restart_pending && !shutdown_pending) { - RESULTCODES proc_rc; - PID child_pid; - int active_children = 0; - - /* Count number of active children */ - for (slot=0; slot < HARD_SERVER_LIMIT; slot++) { - active_children += ap_scoreboard_image->parent[slot].pid != 0 && - !ap_scoreboard_image->parent[slot].quiescing; - } - - /* Spawn children if needed */ - for (slot=0; slot < HARD_SERVER_LIMIT && active_children < ap_daemons_to_start; slot++) { - if (ap_scoreboard_image->parent[slot].pid == 0) { - spawn_child(slot); - active_children++; - } - } - - rc = DosWaitChild(DCWA_PROCESSTREE, DCWW_NOWAIT, &proc_rc, &child_pid, 0); - - if (rc == 0) { - /* A child has terminated, remove its scoreboard entry & terminate if necessary */ - for (slot=0; ap_scoreboard_image->parent[slot].pid != child_pid && slot < HARD_SERVER_LIMIT; slot++); - - if (slot < HARD_SERVER_LIMIT) { - ap_scoreboard_image->parent[slot].pid = 0; - ap_scoreboard_image->parent[slot].quiescing = 0; - - if (proc_rc.codeTerminate == TC_EXIT) { - /* Child terminated normally, check its exit code and - * terminate server if child indicates a fatal error - */ - if (proc_rc.codeResult == APEXIT_CHILDFATAL) - break; - } - } - } else if (rc == ERROR_CHILD_NOT_COMPLETE) { - /* No child exited, lets sleep for a while.... */ - apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL); - } - } - - /* Signal children to shut down, either gracefully or immediately */ - for (slot=0; slot<HARD_SERVER_LIMIT; slot++) { - kill(ap_scoreboard_image->parent[slot].pid, is_graceful ? SIGHUP : SIGTERM); - } - - DosFreeMem(parent_info); - return restart_pending; -} - - - -static void spawn_child(int slot) -{ - PPIB ppib; - PTIB ptib; - char fail_module[100]; - char progname[CCHMAXPATH]; - RESULTCODES proc_rc; - ULONG rc; - - ap_scoreboard_image->parent[slot].generation = ap_my_generation; - DosGetInfoBlocks(&ptib, &ppib); - DosQueryModuleName(ppib->pib_hmte, sizeof(progname), progname); - rc = DosExecPgm(fail_module, sizeof(fail_module), EXEC_ASYNCRESULT, - ppib->pib_pchcmd, NULL, &proc_rc, progname); - - if (rc) { - ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf, - "error spawning child, slot %d", slot); - } - - if (ap_max_daemons_limit < slot) { - ap_max_daemons_limit = slot; - } - - ap_scoreboard_image->parent[slot].pid = proc_rc.codeTerminate; -} - - - -/* Signal handling routines */ - -static void sig_term(int sig) -{ - shutdown_pending = 1; -} - - - -static void sig_restart(int sig) -{ - if (sig == SIGUSR1) { - is_graceful = 1; - } - - restart_pending = 1; -} - - - -static void set_signals() -{ - struct sigaction sa; - - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = sig_term; - - if (sigaction(SIGTERM, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)"); - - if (sigaction(SIGINT, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)"); - - sa.sa_handler = sig_restart; - - if (sigaction(SIGHUP, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)"); - if (sigaction(SIGUSR1, &sa, NULL) < 0) - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGUSR1)"); -} - - - -/* Enquiry functions used get MPM status info */ - -AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) -{ - switch (query_code) { - case AP_MPMQ_MAX_DAEMON_USED: - *result = ap_max_daemons_limit; - return APR_SUCCESS; - case AP_MPMQ_IS_THREADED: - *result = AP_MPMQ_DYNAMIC; - return APR_SUCCESS; - case AP_MPMQ_IS_FORKED: - *result = AP_MPMQ_NOT_SUPPORTED; - return APR_SUCCESS; - case AP_MPMQ_HARD_LIMIT_DAEMONS: - *result = HARD_SERVER_LIMIT; - return APR_SUCCESS; - case AP_MPMQ_HARD_LIMIT_THREADS: - *result = HARD_THREAD_LIMIT; - return APR_SUCCESS; - case AP_MPMQ_MIN_SPARE_DAEMONS: - *result = 0; - return APR_SUCCESS; - case AP_MPMQ_MAX_SPARE_DAEMONS: - *result = 0; - return APR_SUCCESS; - case AP_MPMQ_MAX_REQUESTS_DAEMON: - *result = ap_max_requests_per_child; - return APR_SUCCESS; - } - return APR_ENOTIMPL; -} - - - -int ap_graceful_stop_signalled(void) -{ - return is_graceful; -} - - - -/* Configuration handling stuff */ - -static int mpmt_os2_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp) -{ - one_process = ap_exists_config_define("ONE_PROCESS") || - ap_exists_config_define("DEBUG"); - is_graceful = 0; - ap_listen_pre_config(); - ap_daemons_to_start = DEFAULT_START_DAEMON; - ap_thread_limit = HARD_THREAD_LIMIT; - ap_pid_fname = DEFAULT_PIDLOG; - ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; - ap_extended_status = 0; - ap_min_spare_threads = DEFAULT_MIN_SPARE_THREAD; - ap_max_spare_threads = DEFAULT_MAX_SPARE_THREAD; - - return OK; -} - - - -static void mpmt_os2_hooks(apr_pool_t *p) -{ - ap_hook_pre_config(mpmt_os2_pre_config, NULL, NULL, APR_HOOK_MIDDLE); -} - - - -static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - - if (err != NULL) { - return err; - } - - ap_daemons_to_start = atoi(arg); - return NULL; -} - - - -static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy, - const char *arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - - if (err != NULL) { - return err; - } - - ap_min_spare_threads = atoi(arg); - - if (ap_min_spare_threads <= 0) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, - "WARNING: detected MinSpareThreads set to non-positive."); - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, - "Resetting to 1 to avoid almost certain Apache failure."); - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, - "Please read the documentation."); - ap_min_spare_threads = 1; - } - - return NULL; -} - - - -static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy, - const char *arg) -{ - const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); - - if (err != NULL) { - return err; - } - - ap_max_spare_threads = atoi(arg); - return NULL; -} - - - -static const char *ignore_cmd(cmd_parms *cmd, void *dummy, const char *arg) -{ - return NULL; -} - - - -static const command_rec mpmt_os2_cmds[] = { -LISTEN_COMMANDS, -AP_INIT_TAKE1( "StartServers", set_daemons_to_start, NULL, RSRC_CONF, - "Number of child processes launched at server startup" ), -AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF, - "Minimum number of idle children, to handle request spikes"), -AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF, - "Maximum number of idle children"), -AP_INIT_TAKE1("User", ignore_cmd, NULL, RSRC_CONF, - "Not applicable on this platform"), -AP_INIT_TAKE1("Group", ignore_cmd, NULL, RSRC_CONF, - "Not applicable on this platform"), -AP_INIT_TAKE1("ScoreBoardFile", ignore_cmd, NULL, RSRC_CONF, \ - "Not applicable on this platform"), -{ NULL } -}; - -module AP_MODULE_DECLARE_DATA mpm_mpmt_os2_module = { - MPM20_MODULE_STUFF, - NULL, /* hook to run before apache parses args */ - NULL, /* create per-directory config structure */ - NULL, /* merge per-directory config structures */ - NULL, /* create per-server config structure */ - NULL, /* merge per-server config structures */ - mpmt_os2_cmds, /* command apr_table_t */ - mpmt_os2_hooks, /* register_hooks */ -}; |