FreeBSD Bugzilla – Attachment 98964 Details for
Bug 137953
[patch] update www/apache22 mpm-itk patch to 20090414-00
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 72.50 KB, created by
emikulic
on 2009-08-19 09:20:00 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
emikulic
Created:
2009-08-19 09:20:00 UTC
Size:
72.50 KB
patch
obsolete
>diff -Nur apache22.orig/Makefile apache22/Makefile >--- apache22.orig/Makefile 2009-06-17 03:04:56.000000000 +1000 >+++ apache22/Makefile 2009-06-19 15:41:37.000000000 +1000 >@@ -47,7 +47,7 @@ > USE_RC_SUBR= apache22 htcacheclean > LIBTOOLFILES= configure > >-MPM_ITK_VERSION?= 20080727-00 >+MPM_ITK_VERSION?= 20090414-00 > > # for slave ports > .if !defined(MASTERDIR) >diff -Nur apache22.orig/files/mpm-itk-20090414-00 apache22/files/mpm-itk-20090414-00 >--- apache22.orig/files/mpm-itk-20090414-00 1970-01-01 10:00:00.000000000 +1000 >+++ apache22/files/mpm-itk-20090414-00 2009-06-19 15:45:24.000000000 +1000 >@@ -0,0 +1,2039 @@ >+unchanged: >+--- server/mpm/experimental/itk/Makefile.in 2009-03-17 21:38:54.000000000 +0100 >++++ server/mpm/experimental/itk/Makefile.in 2009-03-17 21:39:03.000000000 +0100 >+@@ -0,0 +1,5 @@ >++ >++LTLIBRARY_NAME = libitk.la >++LTLIBRARY_SOURCES = itk.c >++ >++include $(top_srcdir)/build/ltlib.mk >+unchanged: >+--- server/mpm/experimental/itk/config.m4 2009-03-17 21:38:53.000000000 +0100 >++++ server/mpm/experimental/itk/config.m4 2009-03-17 21:39:03.000000000 +0100 >+@@ -0,0 +1,3 @@ >++if test "$MPM_NAME" = "itk" ; then >++ APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile) >++fi >+diff -u httpd-2.2.11/server/mpm/experimental/itk/itk.c httpd-2.2.11/server/mpm/experimental/itk/itk.c >+--- server/mpm/experimental/itk/itk.c 2009-04-14 23:29:16.000000000 +0200 >++++ server/mpm/experimental/itk/itk.c 2009-04-14 23:31:05.000000000 +0200 >+@@ -0,0 +1,1740 @@ >++/* Licensed to the Apache Software Foundation (ASF) under one or more >++ * contributor license agreements. See the NOTICE file distributed with >++ * this work for additional information regarding copyright ownership. >++ * The ASF licenses this file to You under the Apache License, Version 2.0 >++ * (the "License"); you may not use this file except in compliance with >++ * the License. You may obtain a copy of the License at >++ * >++ * http://www.apache.org/licenses/LICENSE-2.0 >++ * >++ * Unless required by applicable law or agreed to in writing, software >++ * distributed under the License is distributed on an "AS IS" BASIS, >++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >++ * See the License for the specific language governing permissions and >++ * limitations under the License. >++ * >++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@bigfoot.com>. >++ * Licensed under the same terms as the rest of Apache. >++ * >++ * Portions copyright 2008 Knut Auvor Grythe <knut@auvor.no>. >++ * Licensed under the same terms as the rest of Apache. >++ */ >++ >++#include "apr.h" >++#include "apr_portable.h" >++#include "apr_strings.h" >++#include "apr_thread_proc.h" >++#include "apr_signal.h" >++ >++# define _DBG(text,par...) \ >++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \ >++ "(itkmpm: pid=%d uid=%d, gid=%d) %s(): " text, \ >++ getpid(), getuid(), getgid(), __FUNCTION__, par) >++ >++#define APR_WANT_STDIO >++#define APR_WANT_STRFUNC >++#include "apr_want.h" >++ >++#if APR_HAVE_UNISTD_H >++#include <unistd.h> >++#endif >++#if APR_HAVE_SYS_TYPES_H >++#include <sys/types.h> >++#endif >++ >++#define CORE_PRIVATE >++ >++#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 "http_request.h" /* for ap_hook_post_perdir_config */ >++#include "scoreboard.h" >++#include "ap_mpm.h" >++#include "unixd.h" >++#include "mpm_common.h" >++#include "ap_listen.h" >++#include "ap_mmn.h" >++#include "apr_poll.h" >++ >++#ifdef HAVE_BSTRING_H >++#include <bstring.h> /* for IRIX, FD_SET calls bzero() */ >++#endif >++#ifdef HAVE_TIME_H >++#include <time.h> >++#endif >++#ifdef HAVE_SYS_PROCESSOR_H >++#include <sys/processor.h> /* for bindprocessor() */ >++#endif >++ >++#if HAVE_LIBCAP >++#include <sys/capability.h> >++#endif >++ >++#include <signal.h> >++#include <sys/times.h> >++ >++/* Limit on the total --- clients will be locked out if more servers than >++ * this are needed. It is intended solely to keep the server from crashing >++ * when things get out of hand. >++ * >++ * We keep a hard maximum number of servers, for two reasons --- first off, >++ * in case something goes seriously wrong, we want to stop the fork bomb >++ * short of actually crashing the machine we're running on by filling some >++ * kernel table. Secondly, it keeps the size of the scoreboard file small >++ * enough that we can read the whole thing without worrying too much about >++ * the overhead. >++ */ >++#ifndef DEFAULT_SERVER_LIMIT >++#define DEFAULT_SERVER_LIMIT 256 >++#endif >++ >++/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want >++ * some sort of compile-time limit to help catch typos. >++ */ >++#ifndef MAX_SERVER_LIMIT >++#define MAX_SERVER_LIMIT 200000 >++#endif >++ >++#ifndef HARD_THREAD_LIMIT >++#define HARD_THREAD_LIMIT 1 >++#endif >++ >++/* config globals */ >++ >++int ap_threads_per_child=0; /* Worker threads per child */ >++static apr_proc_mutex_t *accept_mutex; >++static int ap_daemons_to_start=0; >++static int ap_daemons_min_free=0; >++static int ap_daemons_max_free=0; >++static int ap_daemons_limit=0; /* MaxClients */ >++static int server_limit = DEFAULT_SERVER_LIMIT; >++static int first_server_limit = 0; >++static int changed_limit_at_restart; >++static int mpm_state = AP_MPMQ_STARTING; >++static ap_pod_t *pod; >++ >++/* >++ * The max child slot ever assigned, preserved across restarts. Necessary >++ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We >++ * use this value to optimize routines that have to scan the entire scoreboard. >++ */ >++int ap_max_daemons_limit = -1; >++server_rec *ap_server_conf; >++ >++/* one_process --- debugging mode variable; can be set from the command line >++ * with the -X flag. If set, this gets you the child_main loop running >++ * in the process which originally started up (no detach, no make_child), >++ * which is a pretty nice debugging environment. (You'll get a SIGHUP >++ * early in standalone_main; just continue through. This is the server >++ * trying to kill off any child processes which it might have lying >++ * around --- Apache doesn't keep track of their pids, it just sends >++ * SIGHUP to the process group, ignoring it in the root process. >++ * Continue through and you'll be fine.). >++ */ >++ >++static int one_process = 0; >++ >++static apr_pool_t *pconf; /* Pool for config stuff */ >++static apr_pool_t *pchild; /* Pool for httpd child stuff */ >++ >++static pid_t ap_my_pid; /* it seems silly to call getpid all the time */ >++static pid_t parent_pid; >++#ifndef MULTITHREAD >++static int my_child_num; >++#endif >++ap_generation_t volatile ap_my_generation=0; >++ >++#ifdef TPF >++int tpf_child = 0; >++char tpf_server_name[INETD_SERVNAME_LENGTH+1]; >++#endif /* TPF */ >++ >++static volatile int die_now = 0; >++ >++#define UNSET_NICE_VALUE 100 >++ >++typedef struct >++{ >++ uid_t uid; >++ gid_t gid; >++ char *username; >++ int nice_value; >++} itk_per_dir_conf; >++ >++typedef struct >++{ >++ int max_clients_vhost; >++} itk_server_conf; >++ >++module AP_MODULE_DECLARE_DATA mpm_itk_module; >++ >++#ifdef GPROF >++/* >++ * change directory for gprof to plop the gmon.out file >++ * configure in httpd.conf: >++ * GprofDir $RuntimeDir/ -> $ServerRoot/$RuntimeDir/gmon.out >++ * GprofDir $RuntimeDir/% -> $ServerRoot/$RuntimeDir/gprof.$pid/gmon.out >++ */ >++static void chdir_for_gprof(void) >++{ >++ core_server_config *sconf = >++ ap_get_module_config(ap_server_conf->module_config, &core_module); >++ char *dir = sconf->gprof_dir; >++ const char *use_dir; >++ >++ if(dir) { >++ apr_status_t res; >++ char *buf = NULL ; >++ int len = strlen(sconf->gprof_dir) - 1; >++ if(*(dir + len) == '%') { >++ dir[len] = '\0'; >++ buf = ap_append_pid(pconf, dir, "gprof."); >++ } >++ use_dir = ap_server_root_relative(pconf, buf ? buf : dir); >++ res = apr_dir_make(use_dir, >++ APR_UREAD | APR_UWRITE | APR_UEXECUTE | >++ APR_GREAD | APR_GEXECUTE | >++ APR_WREAD | APR_WEXECUTE, pconf); >++ if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) { >++ ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf, >++ "gprof: error creating directory %s", dir); >++ } >++ } >++ else { >++ use_dir = ap_server_root_relative(pconf, DEFAULT_REL_RUNTIMEDIR); >++ } >++ >++ chdir(use_dir); >++} >++#else >++#define chdir_for_gprof() >++#endif >++ >++/* XXX - I don't know if TPF will ever use this module or not, so leave >++ * the ap_check_signals calls in but disable them - manoj */ >++#define ap_check_signals() >++ >++/* a clean exit from a child with proper cleanup */ >++static void clean_child_exit(int code) __attribute__ ((noreturn)); >++static void clean_child_exit(int code) >++{ >++ mpm_state = AP_MPMQ_STOPPING; >++ >++ if (pchild) { >++ apr_pool_destroy(pchild); >++ } >++ ap_mpm_pod_close(pod); >++ chdir_for_gprof(); >++ exit(code); >++} >++ >++static void accept_mutex_on(void) >++{ >++ apr_status_t rv = apr_proc_mutex_lock(accept_mutex); >++ if (rv != APR_SUCCESS) { >++ const char *msg = "couldn't grab the accept mutex"; >++ >++ if (ap_my_generation != >++ ap_scoreboard_image->global->running_generation) { >++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg); >++ clean_child_exit(0); >++ } >++ else { >++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg); >++ exit(APEXIT_CHILDFATAL); >++ } >++ } >++} >++ >++static void accept_mutex_off(void) >++{ >++ apr_status_t rv = apr_proc_mutex_unlock(accept_mutex); >++ if (rv != APR_SUCCESS) { >++ const char *msg = "couldn't release the accept mutex"; >++ >++ if (ap_my_generation != >++ ap_scoreboard_image->global->running_generation) { >++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg); >++ /* don't exit here... we have a connection to >++ * process, after which point we'll see that the >++ * generation changed and we'll exit cleanly >++ */ >++ } >++ else { >++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg); >++ exit(APEXIT_CHILDFATAL); >++ } >++ } >++} >++ >++/* On some architectures it's safe to do unserialized accept()s in the single >++ * Listen case. But it's never safe to do it in the case where there's >++ * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT >++ * when it's safe in the single Listen case. >++ */ >++#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT >++#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0) >++#else >++#define SAFE_ACCEPT(stmt) do {stmt;} while(0) >++#endif >++ >++AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) >++{ >++ switch(query_code){ >++ case AP_MPMQ_MAX_DAEMON_USED: >++ *result = ap_daemons_limit; >++ return APR_SUCCESS; >++ case AP_MPMQ_IS_THREADED: >++ *result = AP_MPMQ_NOT_SUPPORTED; >++ return APR_SUCCESS; >++ case AP_MPMQ_IS_FORKED: >++ *result = AP_MPMQ_DYNAMIC; >++ return APR_SUCCESS; >++ case AP_MPMQ_HARD_LIMIT_DAEMONS: >++ *result = server_limit; >++ return APR_SUCCESS; >++ case AP_MPMQ_HARD_LIMIT_THREADS: >++ *result = HARD_THREAD_LIMIT; >++ return APR_SUCCESS; >++ case AP_MPMQ_MAX_THREADS: >++ *result = 0; >++ return APR_SUCCESS; >++ case AP_MPMQ_MIN_SPARE_DAEMONS: >++ *result = ap_daemons_min_free; >++ return APR_SUCCESS; >++ case AP_MPMQ_MIN_SPARE_THREADS: >++ *result = 0; >++ return APR_SUCCESS; >++ case AP_MPMQ_MAX_SPARE_DAEMONS: >++ *result = ap_daemons_max_free; >++ return APR_SUCCESS; >++ case AP_MPMQ_MAX_SPARE_THREADS: >++ *result = 0; >++ return APR_SUCCESS; >++ case AP_MPMQ_MAX_REQUESTS_DAEMON: >++ *result = ap_max_requests_per_child; >++ return APR_SUCCESS; >++ case AP_MPMQ_MAX_DAEMONS: >++ *result = server_limit; >++ return APR_SUCCESS; >++ case AP_MPMQ_MPM_STATE: >++ *result = mpm_state; >++ return APR_SUCCESS; >++ } >++ return APR_ENOTIMPL; >++} >++ >++#if defined(NEED_WAITPID) >++/* >++ Systems without a real waitpid sometimes lose a child's exit while waiting >++ for another. Search through the scoreboard for missing children. >++ */ >++int reap_children(int *exitcode, apr_exit_why_e *status) >++{ >++ int n, pid; >++ >++ for (n = 0; n < ap_max_daemons_limit; ++n) { >++ if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD && >++ kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) { >++ ap_update_child_status_from_indexes(n, 0, SERVER_DEAD, NULL); >++ /* just mark it as having a successful exit status */ >++ *status = APR_PROC_EXIT; >++ *exitcode = 0; >++ return(pid); >++ } >++ } >++ return 0; >++} >++#endif >++ >++/***************************************************************** >++ * Connection structures and accounting... >++ */ >++ >++static void just_die(int sig) >++{ >++ clean_child_exit(0); >++} >++ >++static void stop_listening(int sig) >++{ >++ ap_close_listeners(); >++ >++ /* For a graceful stop, we want the child to exit when done */ >++ die_now = 1; >++} >++ >++/* volatile just in case */ >++static int volatile shutdown_pending; >++static int volatile restart_pending; >++static int volatile is_graceful; >++ >++static void sig_term(int sig) >++{ >++ if (shutdown_pending == 1) { >++ /* Um, is this _probably_ not an error, if the user has >++ * tried to do a shutdown twice quickly, so we won't >++ * worry about reporting it. >++ */ >++ return; >++ } >++ shutdown_pending = 1; >++ is_graceful = (sig == AP_SIG_GRACEFUL_STOP); >++} >++ >++/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL >++ * in the parent process, unless running in ONE_PROCESS mode >++ */ >++static void restart(int sig) >++{ >++ if (restart_pending == 1) { >++ /* Probably not an error - don't bother reporting it */ >++ return; >++ } >++ restart_pending = 1; >++ is_graceful = (sig == AP_SIG_GRACEFUL); >++} >++ >++static void set_signals(void) >++{ >++#ifndef NO_USE_SIGACTION >++ struct sigaction sa; >++#endif >++ >++ if (!one_process) { >++ ap_fatal_signal_setup(ap_server_conf, pconf); >++ } >++ >++#ifndef NO_USE_SIGACTION >++ 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)"); >++#ifdef AP_SIG_GRACEFUL_STOP >++ if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0) >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, >++ "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")"); >++#endif >++#ifdef SIGINT >++ if (sigaction(SIGINT, &sa, NULL) < 0) >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)"); >++#endif >++#ifdef SIGXCPU >++ sa.sa_handler = SIG_DFL; >++ if (sigaction(SIGXCPU, &sa, NULL) < 0) >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)"); >++#endif >++#ifdef SIGXFSZ >++ sa.sa_handler = SIG_DFL; >++ if (sigaction(SIGXFSZ, &sa, NULL) < 0) >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)"); >++#endif >++#ifdef SIGPIPE >++ sa.sa_handler = SIG_IGN; >++ if (sigaction(SIGPIPE, &sa, NULL) < 0) >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)"); >++#endif >++ >++ /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy >++ * processing one >++ */ >++ sigaddset(&sa.sa_mask, SIGHUP); >++ sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL); >++ sa.sa_handler = restart; >++ if (sigaction(SIGHUP, &sa, NULL) < 0) >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)"); >++ if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0) >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")"); >++#else >++ if (!one_process) { >++#ifdef SIGXCPU >++ apr_signal(SIGXCPU, SIG_DFL); >++#endif /* SIGXCPU */ >++#ifdef SIGXFSZ >++ apr_signal(SIGXFSZ, SIG_DFL); >++#endif /* SIGXFSZ */ >++ } >++ >++ apr_signal(SIGTERM, sig_term); >++#ifdef SIGHUP >++ apr_signal(SIGHUP, restart); >++#endif /* SIGHUP */ >++#ifdef AP_SIG_GRACEFUL >++ apr_signal(AP_SIG_GRACEFUL, restart); >++#endif /* AP_SIG_GRACEFUL */ >++#ifdef AP_SIG_GRACEFUL_STOP >++ apr_signal(AP_SIG_GRACEFUL_STOP, sig_term); >++#endif /* AP_SIG_GRACEFUL */ >++#ifdef SIGPIPE >++ apr_signal(SIGPIPE, SIG_IGN); >++#endif /* SIGPIPE */ >++ >++#endif >++} >++ >++/***************************************************************** >++ * Child process main loop. >++ * The following vars are static to avoid getting clobbered by longjmp(); >++ * they are really private to child_main. >++ */ >++ >++static int requests_this_child; >++static int num_listensocks = 0; >++ >++ >++int ap_graceful_stop_signalled(void) >++{ >++ /* not ever called anymore... */ >++ return 0; >++} >++ >++ >++static void child_main(int child_num_arg) >++{ >++ apr_pool_t *ptrans; >++ apr_allocator_t *allocator; >++ apr_status_t status; >++ int i; >++ ap_listen_rec *lr; >++ apr_pollset_t *pollset; >++ ap_sb_handle_t *sbh; >++ apr_bucket_alloc_t *bucket_alloc; >++ int last_poll_idx = 0; >++ >++#if HAVE_LIBCAP >++ cap_t caps; >++ cap_value_t suidcaps[] = { >++ CAP_SETUID, >++ CAP_SETGID, >++ CAP_DAC_READ_SEARCH, >++ CAP_SYS_NICE, >++ }; >++#endif >++ >++ mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this >++ * child initializes >++ */ >++ >++ my_child_num = child_num_arg; >++ ap_my_pid = getpid(); >++ requests_this_child = 0; >++ >++ ap_fatal_signal_child_setup(ap_server_conf); >++ >++ /* Get a sub context for global allocations in this child, so that >++ * we can have cleanups occur when the child exits. >++ */ >++ apr_allocator_create(&allocator); >++ apr_allocator_max_free_set(allocator, ap_max_mem_free); >++ apr_pool_create_ex(&pchild, pconf, NULL, allocator); >++ apr_allocator_owner_set(allocator, pchild); >++ >++ apr_pool_create(&ptrans, pchild); >++ apr_pool_tag(ptrans, "transaction"); >++ >++ /* needs to be done before we switch UIDs so we have permissions */ >++ ap_reopen_scoreboard(pchild, NULL, 0); >++ status = apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild); >++ if (status != APR_SUCCESS) { >++ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, >++ "Couldn't initialize cross-process lock in child " >++ "(%s) (%d)", ap_lock_fname, ap_accept_lock_mech); >++ clean_child_exit(APEXIT_CHILDFATAL); >++ } >++ >++ ap_run_child_init(pchild, ap_server_conf); >++ >++ ap_create_sb_handle(&sbh, pchild, my_child_num, 0); >++ >++ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL); >++ >++ /* Set up the pollfd array */ >++ /* ### check the status */ >++ (void) apr_pollset_create(&pollset, num_listensocks, pchild, 0); >++ >++ for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) { >++ apr_pollfd_t pfd = { 0 }; >++ >++ pfd.desc_type = APR_POLL_SOCKET; >++ pfd.desc.s = lr->sd; >++ pfd.reqevents = APR_POLLIN; >++ pfd.client_data = lr; >++ >++ /* ### check the status */ >++ (void) apr_pollset_add(pollset, &pfd); >++ } >++ >++#if HAVE_LIBCAP >++ /* Drop as many privileges as we can. We'll still >++ * access files with uid=0, and we can setuid() to anything, but >++ * at least there's tons of other evilness (like loading kernel >++ * modules) we can't do directly. (The setuid() capability will >++ * go away automatically when we setuid() or exec() -- the former >++ * is likely to come first.) >++ */ >++ caps = cap_init(); >++ cap_clear(caps); >++ cap_set_flag(caps, CAP_PERMITTED, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET); >++ cap_set_flag(caps, CAP_EFFECTIVE, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET); >++ cap_set_proc(caps); >++ cap_free(caps); >++#endif >++ >++ mpm_state = AP_MPMQ_RUNNING; >++ >++ bucket_alloc = apr_bucket_alloc_create(pchild); >++ >++ /* die_now is set when AP_SIG_GRACEFUL is received in the child; >++ * shutdown_pending is set when SIGTERM is received when running >++ * in single process mode. */ >++ while (!die_now && !shutdown_pending) { >++ conn_rec *current_conn; >++ void *csd; >++ >++ /* >++ * (Re)initialize this child to a pre-connection state. >++ */ >++ >++ apr_pool_clear(ptrans); >++ >++ if ((ap_max_requests_per_child > 0 >++ && requests_this_child++ >= ap_max_requests_per_child)) { >++ clean_child_exit(0); >++ } >++ >++ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL); >++ >++ /* >++ * Wait for an acceptable connection to arrive. >++ */ >++ >++ /* Lock around "accept", if necessary */ >++ SAFE_ACCEPT(accept_mutex_on()); >++ >++ if (num_listensocks == 1) { >++ /* There is only one listener record, so refer to that one. */ >++ lr = ap_listeners; >++ } >++ else { >++ /* multiple listening sockets - need to poll */ >++ for (;;) { >++ apr_int32_t numdesc; >++ const apr_pollfd_t *pdesc; >++ >++ /* timeout == -1 == wait forever */ >++ status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc); >++ if (status != APR_SUCCESS) { >++ if (APR_STATUS_IS_EINTR(status)) { >++ if (one_process && shutdown_pending) { >++ return; >++ } >++ else if (die_now) { >++ /* In graceful stop/restart; drop the mutex >++ * and terminate the child. */ >++ SAFE_ACCEPT(accept_mutex_off()); >++ clean_child_exit(0); >++ } >++ continue; >++ } >++ /* Single Unix documents select as returning errnos >++ * EBADF, EINTR, and EINVAL... and in none of those >++ * cases does it make sense to continue. In fact >++ * on Linux 2.0.x we seem to end up with EFAULT >++ * occasionally, and we'd loop forever due to it. >++ */ >++ ap_log_error(APLOG_MARK, APLOG_ERR, status, >++ ap_server_conf, "apr_pollset_poll: (listen)"); >++ SAFE_ACCEPT(accept_mutex_off()); >++ clean_child_exit(1); >++ } >++ >++ /* We can always use pdesc[0], but sockets at position N >++ * could end up completely starved of attention in a very >++ * busy server. Therefore, we round-robin across the >++ * returned set of descriptors. While it is possible that >++ * the returned set of descriptors might flip around and >++ * continue to starve some sockets, we happen to know the >++ * internal pollset implementation retains ordering >++ * stability of the sockets. Thus, the round-robin should >++ * ensure that a socket will eventually be serviced. >++ */ >++ if (last_poll_idx >= numdesc) >++ last_poll_idx = 0; >++ >++ /* Grab a listener record from the client_data of the poll >++ * descriptor, and advance our saved index to round-robin >++ * the next fetch. >++ * >++ * ### hmm... this descriptor might have POLLERR rather >++ * ### than POLLIN >++ */ >++ lr = pdesc[last_poll_idx++].client_data; >++ goto got_fd; >++ } >++ } >++ got_fd: >++ /* if we accept() something we don't want to die, so we have to >++ * defer the exit >++ */ >++ status = lr->accept_func(&csd, lr, ptrans); >++ >++ SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */ >++ >++ if (status == APR_EGENERAL) { >++ /* resource shortage or should-not-occur occured */ >++ clean_child_exit(1); >++ } >++ else if (status != APR_SUCCESS) { >++ continue; >++ } >++ >++ /* >++ * We now have a connection, so set it up with the appropriate >++ * socket options, file descriptors, and read/write buffers. >++ */ >++ >++ { >++ pid_t pid = fork(), child_pid; >++ int status; >++ switch (pid) { >++ case -1: >++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "fork: Unable to fork new process"); >++ break; >++ case 0: /* child */ >++ apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild); >++ current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc); >++ if (current_conn) { >++ ap_process_connection(current_conn, csd); >++ ap_lingering_close(current_conn); >++ } >++ exit(0); >++ default: /* parent; just wait for child to be done */ >++ do { >++ child_pid = waitpid(pid, &status, 0); >++ } while (child_pid == -1 && errno == EINTR); >++ >++ if (child_pid != pid || !WIFEXITED(status)) { >++ if (WIFSIGNALED(status)) { >++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child died with signal %u", WTERMSIG(status)); >++ } else if (WEXITSTATUS(status) != 0) { >++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child exited with non-zero exit status %u", WEXITSTATUS(status)); >++ } else { >++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "waitpid() failed"); >++ } >++ clean_child_exit(1); >++ } >++ break; >++ } >++ } >++ >++ /* Check the pod and the generation number after processing a >++ * connection so that we'll go away if a graceful restart occurred >++ * while we were processing the connection or we are the lucky >++ * idle server process that gets to die. >++ */ >++ if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */ >++ die_now = 1; >++ } >++ else if (ap_my_generation != >++ ap_scoreboard_image->global->running_generation) { /* restart? */ >++ /* yeah, this could be non-graceful restart, in which case the >++ * parent will kill us soon enough, but why bother checking? >++ */ >++ die_now = 1; >++ } >++ >++ /* if we have already setuid(), die (we can't be used anyhow) */ >++ if (getuid()) >++ die_now = 1; >++ } >++ clean_child_exit(0); >++} >++ >++ >++static int make_child(server_rec *s, int slot) >++{ >++ int pid; >++ >++ if (slot + 1 > ap_max_daemons_limit) { >++ ap_max_daemons_limit = slot + 1; >++ } >++ >++ if (one_process) { >++ apr_signal(SIGHUP, sig_term); >++ /* Don't catch AP_SIG_GRACEFUL in ONE_PROCESS mode :) */ >++ apr_signal(SIGINT, sig_term); >++#ifdef SIGQUIT >++ apr_signal(SIGQUIT, SIG_DFL); >++#endif >++ apr_signal(SIGTERM, sig_term); >++ child_main(slot); >++ return 0; >++ } >++ >++ (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING, >++ (request_rec *) NULL); >++ >++ >++#ifdef _OSD_POSIX >++ /* BS2000 requires a "special" version of fork() before a setuid() call */ >++ if ((pid = os_fork(unixd_config.user_name)) == -1) { >++#elif defined(TPF) >++ if ((pid = os_fork(s, slot)) == -1) { >++#else >++ if ((pid = fork()) == -1) { >++#endif >++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process"); >++ >++ /* fork didn't succeed. Fix the scoreboard or else >++ * it will say SERVER_STARTING forever and ever >++ */ >++ (void) ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, >++ (request_rec *) NULL); >++ >++ /* In case system resources are maxxed out, we don't want >++ * Apache running away with the CPU trying to fork over and >++ * over and over again. >++ */ >++ sleep(10); >++ >++ return -1; >++ } >++ >++ if (!pid) { >++#ifdef HAVE_BINDPROCESSOR >++ /* by default AIX binds to a single processor >++ * this bit unbinds children which will then bind to another cpu >++ */ >++ int status = bindprocessor(BINDPROCESS, (int)getpid(), >++ PROCESSOR_CLASS_ANY); >++ if (status != OK) { >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, >++ ap_server_conf, "processor unbind failed %d", status); >++ } >++#endif >++ RAISE_SIGSTOP(MAKE_CHILD); >++ AP_MONCONTROL(1); >++ /* Disable the parent's signal handlers and set up proper handling in >++ * the child. >++ */ >++ apr_signal(SIGHUP, just_die); >++ apr_signal(SIGTERM, just_die); >++ /* The child process just closes listeners on AP_SIG_GRACEFUL. >++ * The pod is used for signalling the graceful restart. >++ */ >++ apr_signal(AP_SIG_GRACEFUL, stop_listening); >++ child_main(slot); >++ } >++ >++ ap_scoreboard_image->parent[slot].pid = pid; >++ >++ return 0; >++} >++ >++ >++/* start up a bunch of children */ >++static void startup_children(int number_to_start) >++{ >++ int i; >++ >++ for (i = 0; number_to_start && i < ap_daemons_limit; ++i) { >++ if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) { >++ continue; >++ } >++ if (make_child(ap_server_conf, i) < 0) { >++ break; >++ } >++ --number_to_start; >++ } >++} >++ >++ >++/* >++ * idle_spawn_rate is the number of children that will be spawned on the >++ * next maintenance cycle if there aren't enough idle servers. It is >++ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by >++ * without the need to spawn. >++ */ >++static int idle_spawn_rate = 1; >++#ifndef MAX_SPAWN_RATE >++#define MAX_SPAWN_RATE (32) >++#endif >++static int hold_off_on_exponential_spawning; >++ >++static void perform_idle_server_maintenance(apr_pool_t *p) >++{ >++ int i; >++ int to_kill; >++ int idle_count; >++ worker_score *ws; >++ int free_length; >++ int free_slots[MAX_SPAWN_RATE]; >++ int last_non_dead; >++ int total_non_dead; >++ >++ /* initialize the free_list */ >++ free_length = 0; >++ >++ to_kill = -1; >++ idle_count = 0; >++ last_non_dead = -1; >++ total_non_dead = 0; >++ >++ for (i = 0; i < ap_daemons_limit; ++i) { >++ int status; >++ >++ if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate) >++ break; >++ ws = &ap_scoreboard_image->servers[i][0]; >++ status = ws->status; >++ if (status == SERVER_DEAD) { >++ /* try to keep children numbers as low as possible */ >++ if (free_length < idle_spawn_rate) { >++ free_slots[free_length] = i; >++ ++free_length; >++ } >++ } >++ else { >++ /* We consider a starting server as idle because we started it >++ * at least a cycle ago, and if it still hasn't finished starting >++ * then we're just going to swamp things worse by forking more. >++ * So we hopefully won't need to fork more if we count it. >++ * This depends on the ordering of SERVER_READY and SERVER_STARTING. >++ */ >++ if (status <= SERVER_READY) { >++ ++ idle_count; >++ /* always kill the highest numbered child if we have to... >++ * no really well thought out reason ... other than observing >++ * the server behaviour under linux where lower numbered children >++ * tend to service more hits (and hence are more likely to have >++ * their data in cpu caches). >++ */ >++ to_kill = i; >++ } >++ >++ ++total_non_dead; >++ last_non_dead = i; >++ } >++ } >++ ap_max_daemons_limit = last_non_dead + 1; >++ if (idle_count > ap_daemons_max_free) { >++ /* kill off one child... we use the pod because that'll cause it to >++ * shut down gracefully, in case it happened to pick up a request >++ * while we were counting >++ */ >++ ap_mpm_pod_signal(pod); >++ idle_spawn_rate = 1; >++ } >++ else if (idle_count < ap_daemons_min_free) { >++ /* terminate the free list */ >++ if (free_length == 0) { >++ /* only report this condition once */ >++ static int reported = 0; >++ >++ if (!reported) { >++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, >++ "server reached MaxClients setting, consider" >++ " raising the MaxClients setting"); >++ reported = 1; >++ } >++ idle_spawn_rate = 1; >++ } >++ else { >++ if (idle_spawn_rate >= 8) { >++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, >++ "server seems busy, (you may need " >++ "to increase StartServers, or Min/MaxSpareServers), " >++ "spawning %d children, there are %d idle, and " >++ "%d total children", idle_spawn_rate, >++ idle_count, total_non_dead); >++ } >++ for (i = 0; i < free_length; ++i) { >++#ifdef TPF >++ if (make_child(ap_server_conf, free_slots[i]) == -1) { >++ if(free_length == 1) { >++ shutdown_pending = 1; >++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, ap_server_conf, >++ "No active child processes: shutting down"); >++ } >++ } >++#else >++ make_child(ap_server_conf, free_slots[i]); >++#endif /* TPF */ >++ } >++ /* the next time around we want to spawn twice as many if this >++ * wasn't good enough, but not if we've just done a graceful >++ */ >++ if (hold_off_on_exponential_spawning) { >++ --hold_off_on_exponential_spawning; >++ } >++ else if (idle_spawn_rate < MAX_SPAWN_RATE) { >++ idle_spawn_rate *= 2; >++ } >++ } >++ } >++ else { >++ idle_spawn_rate = 1; >++ } >++} >++ >++/***************************************************************** >++ * Executive routines. >++ */ >++ >++int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) >++{ >++ int index; >++ int remaining_children_to_start; >++ apr_status_t rv; >++ >++ ap_log_pid(pconf, ap_pid_fname); >++ >++ first_server_limit = server_limit; >++ if (changed_limit_at_restart) { >++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, >++ "WARNING: Attempt to change ServerLimit " >++ "ignored during restart"); >++ changed_limit_at_restart = 0; >++ } >++ >++ /* Initialize cross-process accept lock */ >++ ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT, >++ ap_server_root_relative(_pconf, ap_lock_fname), >++ ap_my_pid); >++ >++ rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname, >++ ap_accept_lock_mech, _pconf); >++ if (rv != APR_SUCCESS) { >++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, >++ "Couldn't create accept lock (%s) (%d)", >++ ap_lock_fname, ap_accept_lock_mech); >++ mpm_state = AP_MPMQ_STOPPING; >++ return 1; >++ } >++ >++#if APR_USE_SYSVSEM_SERIALIZE >++ if (ap_accept_lock_mech == APR_LOCK_DEFAULT || >++ ap_accept_lock_mech == APR_LOCK_SYSVSEM) { >++#else >++ if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) { >++#endif >++ rv = unixd_set_proc_mutex_perms(accept_mutex); >++ if (rv != APR_SUCCESS) { >++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, >++ "Couldn't set permissions on cross-process lock; " >++ "check User and Group directives"); >++ mpm_state = AP_MPMQ_STOPPING; >++ return 1; >++ } >++ } >++ >++ if (!is_graceful) { >++ if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) { >++ mpm_state = AP_MPMQ_STOPPING; >++ return 1; >++ } >++ /* fix the generation number in the global score; we just got a new, >++ * cleared scoreboard >++ */ >++ ap_scoreboard_image->global->running_generation = ap_my_generation; >++ } >++ >++ set_signals(); >++ >++ if (one_process) { >++ AP_MONCONTROL(1); >++ make_child(ap_server_conf, 0); >++ } >++ else { >++ if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */ >++ ap_daemons_max_free = ap_daemons_min_free + 1; >++ >++ /* If we're doing a graceful_restart then we're going to see a lot >++ * of children exiting immediately when we get into the main loop >++ * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty >++ * rapidly... and for each one that exits we'll start a new one until >++ * we reach at least daemons_min_free. But we may be permitted to >++ * start more than that, so we'll just keep track of how many we're >++ * supposed to start up without the 1 second penalty between each fork. >++ */ >++ remaining_children_to_start = ap_daemons_to_start; >++ if (remaining_children_to_start > ap_daemons_limit) { >++ remaining_children_to_start = ap_daemons_limit; >++ } >++ if (!is_graceful) { >++ startup_children(remaining_children_to_start); >++ remaining_children_to_start = 0; >++ } >++ else { >++ /* give the system some time to recover before kicking into >++ * exponential mode >++ */ >++ hold_off_on_exponential_spawning = 10; >++ } >++ >++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, >++ "%s configured -- resuming normal operations", >++ ap_get_server_description()); >++ 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 >++ restart_pending = shutdown_pending = 0; >++ >++ mpm_state = AP_MPMQ_RUNNING; >++ >++ while (!restart_pending && !shutdown_pending) { >++ int child_slot; >++ apr_exit_why_e exitwhy; >++ int status, processed_status; >++ /* this is a memory leak, but I'll fix it later. */ >++ apr_proc_t pid; >++ >++ ap_wait_or_timeout(&exitwhy, &status, &pid, pconf); >++ >++ /* XXX: if it takes longer than 1 second for all our children >++ * to start up and get into IDLE state then we may spawn an >++ * extra child >++ */ >++ if (pid.pid != -1) { >++ processed_status = ap_process_child_status(&pid, exitwhy, status); >++ if (processed_status == APEXIT_CHILDFATAL) { >++ mpm_state = AP_MPMQ_STOPPING; >++ return 1; >++ } >++ >++ /* non-fatal death... note that it's gone in the scoreboard. */ >++ child_slot = find_child_by_pid(&pid); >++ if (child_slot >= 0) { >++ (void) ap_update_child_status_from_indexes(child_slot, 0, SERVER_DEAD, >++ (request_rec *) NULL); >++ if (processed_status == APEXIT_CHILDSICK) { >++ /* child detected a resource shortage (E[NM]FILE, ENOBUFS, etc) >++ * cut the fork rate to the minimum >++ */ >++ idle_spawn_rate = 1; >++ } >++ else if (remaining_children_to_start >++ && child_slot < ap_daemons_limit) { >++ /* we're still doing a 1-for-1 replacement of dead >++ * children with new children >++ */ >++ make_child(ap_server_conf, child_slot); >++ --remaining_children_to_start; >++ } >++#if APR_HAS_OTHER_CHILD >++ } >++ else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH, status) == APR_SUCCESS) { >++ /* handled */ >++#endif >++ } >++ else if (is_graceful) { >++ /* Great, we've probably just lost a slot in the >++ * scoreboard. Somehow we don't know about this >++ * child. >++ */ >++ ap_log_error(APLOG_MARK, APLOG_WARNING, >++ 0, ap_server_conf, >++ "long lost child came home! (pid %ld)", (long)pid.pid); >++ } >++ /* Don't perform idle maintenance when a child dies, >++ * only do it when there's a timeout. Remember only a >++ * finite number of children can die, and it's pretty >++ * pathological for a lot to die suddenly. >++ */ >++ continue; >++ } >++ else if (remaining_children_to_start) { >++ /* we hit a 1 second timeout in which none of the previous >++ * generation of children needed to be reaped... so assume >++ * they're all done, and pick up the slack if any is left. >++ */ >++ startup_children(remaining_children_to_start); >++ remaining_children_to_start = 0; >++ /* In any event we really shouldn't do the code below because >++ * few of the servers we just started are in the IDLE state >++ * yet, so we'd mistakenly create an extra server. >++ */ >++ continue; >++ } >++ >++ perform_idle_server_maintenance(pconf); >++#ifdef TPF >++ shutdown_pending = os_check_server(tpf_server_name); >++ ap_check_signals(); >++ sleep(1); >++#endif /*TPF */ >++ } >++ } /* one_process */ >++ >++ mpm_state = AP_MPMQ_STOPPING; >++ >++ if (shutdown_pending && !is_graceful) { >++ /* Time to shut down: >++ * Kill child processes, tell them to call child_exit, etc... >++ */ >++ if (unixd_killpg(getpgrp(), SIGTERM) < 0) { >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM"); >++ } >++ ap_reclaim_child_processes(1); /* Start with SIGTERM */ >++ >++ /* cleanup pid file on normal shutdown */ >++ { >++ const char *pidfile = NULL; >++ pidfile = ap_server_root_relative (pconf, ap_pid_fname); >++ if ( pidfile != NULL && unlink(pidfile) == 0) >++ ap_log_error(APLOG_MARK, APLOG_INFO, >++ 0, ap_server_conf, >++ "removed PID file %s (pid=%ld)", >++ pidfile, (long)getpid()); >++ } >++ >++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, >++ "caught SIGTERM, shutting down"); >++ >++ return 1; >++ } else if (shutdown_pending) { >++ /* Time to perform a graceful shut down: >++ * Reap the inactive children, and ask the active ones >++ * to close their listeners, then wait until they are >++ * all done to exit. >++ */ >++ int active_children; >++ apr_time_t cutoff = 0; >++ >++ /* Stop listening */ >++ ap_close_listeners(); >++ >++ /* kill off the idle ones */ >++ ap_mpm_pod_killpg(pod, ap_max_daemons_limit); >++ >++ /* Send SIGUSR1 to the active children */ >++ active_children = 0; >++ for (index = 0; index < ap_daemons_limit; ++index) { >++ if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { >++ /* Ask each child to close its listeners. */ >++ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL); >++ active_children++; >++ } >++ } >++ >++ /* Allow each child which actually finished to exit */ >++ ap_relieve_child_processes(); >++ >++ /* cleanup pid file */ >++ { >++ const char *pidfile = NULL; >++ pidfile = ap_server_root_relative (pconf, ap_pid_fname); >++ if ( pidfile != NULL && unlink(pidfile) == 0) >++ ap_log_error(APLOG_MARK, APLOG_INFO, >++ 0, ap_server_conf, >++ "removed PID file %s (pid=%ld)", >++ pidfile, (long)getpid()); >++ } >++ >++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, >++ "caught " AP_SIG_GRACEFUL_STOP_STRING ", shutting down gracefully"); >++ >++ if (ap_graceful_shutdown_timeout) { >++ cutoff = apr_time_now() + >++ apr_time_from_sec(ap_graceful_shutdown_timeout); >++ } >++ >++ /* Don't really exit until each child has finished */ >++ shutdown_pending = 0; >++ do { >++ /* Pause for a second */ >++ sleep(1); >++ >++ /* Relieve any children which have now exited */ >++ ap_relieve_child_processes(); >++ >++ active_children = 0; >++ for (index = 0; index < ap_daemons_limit; ++index) { >++ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { >++ active_children = 1; >++ /* Having just one child is enough to stay around */ >++ break; >++ } >++ } >++ } while (!shutdown_pending && active_children && >++ (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff)); >++ >++ /* We might be here because we received SIGTERM, either >++ * way, try and make sure that all of our processes are >++ * really dead. >++ */ >++ unixd_killpg(getpgrp(), SIGTERM); >++ >++ return 1; >++ } >++ >++ /* we've been told to restart */ >++ apr_signal(SIGHUP, SIG_IGN); >++ apr_signal(AP_SIG_GRACEFUL, SIG_IGN); >++ if (one_process) { >++ /* not worth thinking about */ >++ return 1; >++ } >++ >++ /* advance to the next generation */ >++ /* XXX: we really need to make sure this new generation number isn't in >++ * use by any of the children. >++ */ >++ ++ap_my_generation; >++ ap_scoreboard_image->global->running_generation = ap_my_generation; >++ >++ if (is_graceful) { >++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, >++ "Graceful restart requested, doing restart"); >++ >++ /* kill off the idle ones */ >++ ap_mpm_pod_killpg(pod, ap_max_daemons_limit); >++ >++ /* This is mostly for debugging... so that we know what is still >++ * gracefully dealing with existing request. This will break >++ * in a very nasty way if we ever have the scoreboard totally >++ * file-based (no shared memory) >++ */ >++ for (index = 0; index < ap_daemons_limit; ++index) { >++ if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { >++ ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL; >++ /* Ask each child to close its listeners. >++ * >++ * NOTE: we use the scoreboard, because if we send SIGUSR1 >++ * to every process in the group, this may include CGI's, >++ * piped loggers, etc. They almost certainly won't handle >++ * it gracefully. >++ */ >++ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); >++ } >++ } >++ } >++ else { >++ /* Kill 'em off */ >++ if (unixd_killpg(getpgrp(), SIGHUP) < 0) { >++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGHUP"); >++ } >++ ap_reclaim_child_processes(0); /* Not when just starting up */ >++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, >++ "SIGHUP received. Attempting to restart"); >++ } >++ >++ return 0; >++} >++ >++/* This really should be a post_config hook, but the error log is already >++ * redirected by that point, so we need to do this in the open_logs phase. >++ */ >++static int itk_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) >++{ >++ apr_status_t rv; >++ >++ pconf = p; >++ ap_server_conf = s; >++ >++ if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) { >++ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0, >++ NULL, "no listening sockets available, shutting down"); >++ return DONE; >++ } >++ >++ if ((rv = ap_mpm_pod_open(pconf, &pod))) { >++ ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_STARTUP, rv, NULL, >++ "Could not open pipe-of-death."); >++ return DONE; >++ } >++ return OK; >++} >++ >++static int itk_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp) >++{ >++ static int restart_num = 0; >++ int no_detach, debug, foreground; >++ apr_status_t rv; >++ >++ mpm_state = AP_MPMQ_STARTING; >++ >++ debug = ap_exists_config_define("DEBUG"); >++ >++ if (debug) { >++ foreground = one_process = 1; >++ no_detach = 0; >++ } >++ else >++ { >++ no_detach = ap_exists_config_define("NO_DETACH"); >++ one_process = ap_exists_config_define("ONE_PROCESS"); >++ foreground = ap_exists_config_define("FOREGROUND"); >++ } >++ >++ /* sigh, want this only the second time around */ >++ if (restart_num++ == 1) { >++ is_graceful = 0; >++ >++ if (!one_process && !foreground) { >++ rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND >++ : APR_PROC_DETACH_DAEMONIZE); >++ if (rv != APR_SUCCESS) { >++ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, >++ "apr_proc_detach failed"); >++ return HTTP_INTERNAL_SERVER_ERROR; >++ } >++ } >++ >++ parent_pid = ap_my_pid = getpid(); >++ } >++ >++ unixd_pre_config(ptemp); >++ ap_listen_pre_config(); >++ ap_daemons_to_start = DEFAULT_START_DAEMON; >++ ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON; >++ ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON; >++ ap_daemons_limit = server_limit; >++ ap_pid_fname = DEFAULT_PIDLOG; >++ ap_lock_fname = DEFAULT_LOCKFILE; >++ ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; >++ ap_extended_status = 0; >++#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE >++ ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED; >++#endif >++ >++ apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir)); >++ >++ return OK; >++} >++ >++static int itk_post_perdir_config(request_rec *r) >++{ >++ uid_t wanted_uid; >++ gid_t wanted_gid; >++ const char *wanted_username; >++ int err = 0; >++ >++ itk_server_conf *sconf = >++ (itk_server_conf *) ap_get_module_config(r->server->module_config, &mpm_itk_module); >++ >++ /* Enforce MaxClientsVhost. */ >++ if (sconf->max_clients_vhost > 0) { >++ int i, num_other_servers = 0; >++ for (i = 0; i < ap_daemons_limit; ++i) { >++ worker_score *ws = &ap_scoreboard_image->servers[i][0]; >++ if (ws->status >= SERVER_BUSY_READ && strncmp(ws->vhost, r->server->server_hostname, 31) == 0) >++ ++num_other_servers; >++ } >++ >++ if (num_other_servers > sconf->max_clients_vhost) { >++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \ >++ "MaxClientsVhost reached for %s, refusing client.", >++ r->server->server_hostname); >++ return HTTP_SERVICE_UNAVAILABLE; >++ } >++ } >++ >++ itk_per_dir_conf *dconf = >++ (itk_per_dir_conf *) ap_get_module_config(r->per_dir_config, &mpm_itk_module); >++ >++ strncpy(ap_scoreboard_image->servers[my_child_num][0].vhost, r->server->server_hostname, 31); >++ ap_scoreboard_image->servers[my_child_num][0].vhost[31] = 0; >++ >++ if (dconf->nice_value != UNSET_NICE_VALUE && >++ setpriority(PRIO_PROCESS, 0, dconf->nice_value)) { >++ _DBG("setpriority(): %s", strerror(errno)); >++ err = 1; >++ } >++ >++ wanted_uid = dconf->uid; >++ wanted_gid = dconf->gid; >++ wanted_username = dconf->username; >++ >++ if (wanted_uid == -1 || wanted_gid == -1) { >++ wanted_uid = unixd_config.user_id; >++ wanted_gid = unixd_config.group_id; >++ wanted_username = unixd_config.user_name; >++ } >++ >++ if (!err && wanted_uid != -1 && wanted_gid != -1 && (getuid() != wanted_uid || getgid() != wanted_gid)) { >++ if (setgid(wanted_gid)) { >++ _DBG("setgid(%d): %s", wanted_gid, strerror(errno)); >++ err = 1; >++ } else if (initgroups(wanted_username, wanted_gid)) { >++ _DBG("initgroups(%s, %d): %s", wanted_username, wanted_gid, strerror(errno)); >++ err = 1; >++ } else if (setuid(wanted_uid)) { >++ _DBG("setuid(%d): %s", wanted_uid, strerror(errno)); >++ err = 1; >++ } >++ } >++ >++ /* >++ * Most likely a case of switching uid/gid within a persistent >++ * connection; the RFCs allow us to just close the connection >++ * at anytime, so we excercise our right. :-) >++ */ >++ if (err) { >++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \ >++ "Couldn't set uid/gid/priority, closing connection."); >++ ap_lingering_close(r->connection); >++ exit(0); >++ } >++ return OK; >++} >++ >++static void itk_hooks(apr_pool_t *p) >++{ >++ /* The itk open_logs phase must run before the core's, or stderr >++ * will be redirected to a file, and the messages won't print to the >++ * console. >++ */ >++ static const char *const aszSucc[] = {"core.c", NULL}; >++ >++#ifdef AUX3 >++ (void) set42sig(); >++#endif >++ >++ ap_hook_open_logs(itk_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE); >++ /* we need to set the MPM state before other pre-config hooks use MPM query >++ * to retrieve it, so register as REALLY_FIRST >++ */ >++ ap_hook_pre_config(itk_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST); >++ >++ /* set the uid as fast as possible, but not before merging per-dit config */ >++ ap_hook_header_parser(itk_post_perdir_config, NULL, NULL, APR_HOOK_REALLY_FIRST); >++} >++ >++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_free_servers(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_min_free = atoi(arg); >++ if (ap_daemons_min_free <= 0) { >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ "WARNING: detected MinSpareServers 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_daemons_min_free = 1; >++ } >++ >++ return NULL; >++} >++ >++static const char *set_max_free_servers(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_max_free = atoi(arg); >++ return NULL; >++} >++ >++static const char *set_max_clients (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_limit = atoi(arg); >++ if (ap_daemons_limit > server_limit) { >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ "WARNING: MaxClients of %d exceeds ServerLimit value " >++ "of %d servers,", ap_daemons_limit, server_limit); >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ " lowering MaxClients to %d. To increase, please " >++ "see the ServerLimit", server_limit); >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ " directive."); >++ ap_daemons_limit = server_limit; >++ } >++ else if (ap_daemons_limit < 1) { >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ "WARNING: Require MaxClients > 0, setting to 1"); >++ ap_daemons_limit = 1; >++ } >++ return NULL; >++} >++ >++static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) >++{ >++ int tmp_server_limit; >++ >++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); >++ if (err != NULL) { >++ return err; >++ } >++ >++ tmp_server_limit = atoi(arg); >++ /* you cannot change ServerLimit across a restart; ignore >++ * any such attempts >++ */ >++ if (first_server_limit && >++ tmp_server_limit != server_limit) { >++ /* how do we log a message? the error log is a bit bucket at this >++ * point; we'll just have to set a flag so that ap_mpm_run() >++ * logs a warning later >++ */ >++ changed_limit_at_restart = 1; >++ return NULL; >++ } >++ server_limit = tmp_server_limit; >++ >++ if (server_limit > MAX_SERVER_LIMIT) { >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ "WARNING: ServerLimit of %d exceeds compile time limit " >++ "of %d servers,", server_limit, MAX_SERVER_LIMIT); >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ " lowering ServerLimit to %d.", MAX_SERVER_LIMIT); >++ server_limit = MAX_SERVER_LIMIT; >++ } >++ else if (server_limit < 1) { >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ "WARNING: Require ServerLimit > 0, setting to 1"); >++ server_limit = 1; >++ } >++ return NULL; >++} >++ >++static const char *assign_user_id (cmd_parms *cmd, void *ptr, const char *user_name, const char *group_name) >++{ >++ itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr; >++ dconf->username = apr_pstrdup(cmd->pool, user_name); >++ dconf->uid = ap_uname2id(user_name); >++ dconf->gid = ap_gname2id(group_name); >++ return NULL; >++} >++ >++static const char *set_max_clients_vhost (cmd_parms *cmd, void *dummy, const char *arg) >++{ >++ itk_server_conf *sconf = >++ (itk_server_conf *) ap_get_module_config(cmd->server->module_config, &mpm_itk_module); >++ sconf->max_clients_vhost = atoi(arg); >++ return NULL; >++} >++ >++static const char *set_nice_value (cmd_parms *cmd, void *ptr, const char *arg) >++{ >++ itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr; >++ int nice_value = atoi(arg); >++ >++ if (nice_value < -20) { >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ "WARNING: NiceValue of %d is below -20, increasing NiceValue to -20.", >++ nice_value); >++ nice_value = -20; >++ } >++ else if (nice_value > 19) { >++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, >++ "WARNING: NiceValue of %d is above 19, lowering NiceValue to 19.", >++ nice_value); >++ nice_value = 19; >++ } >++ dconf->nice_value = nice_value; >++ return NULL; >++} >++ >++static const command_rec itk_cmds[] = { >++UNIX_DAEMON_COMMANDS, >++LISTEN_COMMANDS, >++AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF, >++ "Number of child processes launched at server startup"), >++AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF, >++ "Minimum number of idle children, to handle request spikes"), >++AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF, >++ "Maximum number of idle children"), >++AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF, >++ "Maximum number of children alive at the same time"), >++AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF, >++ "Maximum value of MaxClients for this run of Apache"), >++AP_INIT_TAKE2("AssignUserID", assign_user_id, NULL, RSRC_CONF|ACCESS_CONF, >++ "Tie a virtual host to a specific child process."), >++AP_INIT_TAKE1("MaxClientsVHost", set_max_clients_vhost, NULL, RSRC_CONF, >++ "Maximum number of children alive at the same time for this virtual host."), >++AP_INIT_TAKE1("NiceValue", set_nice_value, NULL, RSRC_CONF|ACCESS_CONF, >++ "Set nice value for the given vhost, from -20 (highest priority) to 19 (lowest priority)."), >++AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND, >++{ NULL } >++}; >++ >++/* == allocate a private per-dir config structure == */ >++static void *itk_create_dir_config(apr_pool_t *p, char *dummy) >++{ >++ itk_per_dir_conf *c = (itk_per_dir_conf *) >++ apr_pcalloc(p, sizeof(itk_per_dir_conf)); >++ c->uid = c->gid = -1; >++ c->nice_value = UNSET_NICE_VALUE; >++ return c; >++} >++ >++/* == merge the parent per-dir config structure into ours == */ >++static void *itk_merge_dir_config(apr_pool_t *p, void *parent_ptr, void *child_ptr) >++{ >++ itk_per_dir_conf *c = (itk_per_dir_conf *) >++ apr_pcalloc(p, sizeof(itk_per_dir_conf)); >++ itk_per_dir_conf *parent = (itk_per_dir_conf *) parent_ptr; >++ itk_per_dir_conf *child = (itk_per_dir_conf *) child_ptr; >++ >++ if (child->username != NULL) { >++ c->username = apr_pstrdup(p, child->username); >++ c->uid = child->uid; >++ c->gid = child->gid; >++ } else if (parent->username != NULL) { >++ c->username = apr_pstrdup(p, parent->username); >++ c->uid = parent->uid; >++ c->gid = parent->gid; >++ } >++ if (child->nice_value != UNSET_NICE_VALUE) { >++ c->nice_value = child->nice_value; >++ } else { >++ c->nice_value = parent->nice_value; >++ } >++ return c; >++} >++ >++/* == allocate a private server config structure == */ >++static void *itk_create_server_config(apr_pool_t *p, server_rec *s) >++{ >++ itk_server_conf *c = (itk_server_conf *) >++ apr_pcalloc(p, sizeof(itk_server_conf)); >++ c->max_clients_vhost = -1; >++ return c; >++} >++ >++module AP_MODULE_DECLARE_DATA mpm_itk_module = { >++ MPM20_MODULE_STUFF, >++ ap_mpm_rewrite_args, /* hook to run before apache parses args */ >++ itk_create_dir_config, /* create per-directory config structure */ >++ itk_merge_dir_config, /* merge per-directory config structures */ >++ itk_create_server_config, /* create per-server config structure */ >++ NULL, /* merge per-server config structures */ >++ itk_cmds, /* command apr_table_t */ >++ itk_hooks, /* register hooks */ >++}; >+unchanged: >+--- server/mpm/experimental/itk/mpm.h 2009-03-17 21:39:03.000000000 +0100 >++++ server/mpm/experimental/itk/mpm.h 2009-03-21 13:02:33.000000000 +0100 >+@@ -0,0 +1,68 @@ >++/* Licensed to the Apache Software Foundation (ASF) under one or more >++ * contributor license agreements. See the NOTICE file distributed with >++ * this work for additional information regarding copyright ownership. >++ * The ASF licenses this file to You under the Apache License, Version 2.0 >++ * (the "License"); you may not use this file except in compliance with >++ * the License. You may obtain a copy of the License at >++ * >++ * http://www.apache.org/licenses/LICENSE-2.0 >++ * >++ * Unless required by applicable law or agreed to in writing, software >++ * distributed under the License is distributed on an "AS IS" BASIS, >++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >++ * See the License for the specific language governing permissions and >++ * limitations under the License. >++ * >++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@bigfoot.com>. >++ * Licensed under the same terms as the rest of Apache. >++ * >++ * Portions copyright 2008 Knut Auvor Grythe <knut@auvor.no>. >++ * Licensed under the same terms as the rest of Apache. >++ */ >++ >++/** >++ * @file itk/mpm.h >++ * @brief ITK MPM (setuid per-vhost, no threads) >++ * >++ * @defgroup APACHE_MPM_ITK Apache ITK >++ * @ingroup APACHE_MPM APACHE_OS_UNIX >++ * @{ >++ */ >++ >++#include "httpd.h" >++#include "mpm_default.h" >++#include "scoreboard.h" >++#include "unixd.h" >++ >++#ifndef APACHE_MPM_ITK_H >++#define APACHE_MPM_ITK_H >++ >++#define ITK_MPM >++ >++#define MPM_NAME "ITK" >++ >++#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES >++#define AP_MPM_WANT_WAIT_OR_TIMEOUT >++#define AP_MPM_WANT_PROCESS_CHILD_STATUS >++#define AP_MPM_WANT_SET_PIDFILE >++#define AP_MPM_WANT_SET_SCOREBOARD >++#define AP_MPM_WANT_SET_LOCKFILE >++#define AP_MPM_WANT_SET_MAX_REQUESTS >++#define AP_MPM_WANT_SET_COREDUMPDIR >++#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH >++#define AP_MPM_WANT_SIGNAL_SERVER >++#define AP_MPM_WANT_SET_MAX_MEM_FREE >++#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER >++#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN >++#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK >++ >++#define AP_MPM_USES_POD 1 >++#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid) >++#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0) >++#define MPM_ACCEPT_FUNC unixd_accept >++ >++extern int ap_threads_per_child; >++extern int ap_max_daemons_limit; >++extern server_rec *ap_server_conf; >++#endif /* APACHE_MPM_ITK_H */ >++/** @} */ >+unchanged: >+--- server/mpm/experimental/itk/mpm_default.h 2009-03-17 21:39:03.000000000 +0100 >++++ server/mpm/experimental/itk/mpm_default.h 2009-03-21 13:02:33.000000000 +0100 >+@@ -0,0 +1,80 @@ >++/* Licensed to the Apache Software Foundation (ASF) under one or more >++ * contributor license agreements. See the NOTICE file distributed with >++ * this work for additional information regarding copyright ownership. >++ * The ASF licenses this file to You under the Apache License, Version 2.0 >++ * (the "License"); you may not use this file except in compliance with >++ * the License. You may obtain a copy of the License at >++ * >++ * http://www.apache.org/licenses/LICENSE-2.0 >++ * >++ * Unless required by applicable law or agreed to in writing, software >++ * distributed under the License is distributed on an "AS IS" BASIS, >++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >++ * See the License for the specific language governing permissions and >++ * limitations under the License. >++ * >++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@bigfoot.com>. >++ * Licensed under the same terms as the rest of Apache. >++ * >++ * Portions copyright 2008 Knut Auvor Grythe <knut@auvor.no>. >++ * Licensed under the same terms as the rest of Apache. >++ */ >++ >++/** >++ * @file itk/mpm_default.h >++ * @brief ITK MPM defaults >++ * >++ * @addtogroup APACHE_MPM_ITK >++ * @{ >++ */ >++ >++#ifndef APACHE_MPM_DEFAULT_H >++#define APACHE_MPM_DEFAULT_H >++ >++/* Number of servers to spawn off by default --- also, if fewer than >++ * this free when the caretaker checks, it will spawn more. >++ */ >++#ifndef DEFAULT_START_DAEMON >++#define DEFAULT_START_DAEMON 5 >++#endif >++ >++/* Maximum number of *free* server processes --- more than this, and >++ * they will die off. >++ */ >++ >++#ifndef DEFAULT_MAX_FREE_DAEMON >++#define DEFAULT_MAX_FREE_DAEMON 10 >++#endif >++ >++/* Minimum --- fewer than this, and more will be created */ >++ >++#ifndef DEFAULT_MIN_FREE_DAEMON >++#define DEFAULT_MIN_FREE_DAEMON 5 >++#endif >++ >++/* File used for accept locking, when we use a file */ >++#ifndef DEFAULT_LOCKFILE >++#define DEFAULT_LOCKFILE DEFAULT_REL_RUNTIMEDIR "/accept.lock" >++#endif >++ >++/* Where the main/parent process's pid is logged */ >++#ifndef DEFAULT_PIDLOG >++#define DEFAULT_PIDLOG DEFAULT_REL_RUNTIMEDIR "/httpd.pid" >++#endif >++ >++/* >++ * Interval, in microseconds, between scoreboard maintenance. >++ */ >++#ifndef SCOREBOARD_MAINTENANCE_INTERVAL >++#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000 >++#endif >++ >++/* Number of requests to try to handle in a single process. If <= 0, >++ * the children don't die off. >++ */ >++#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD >++#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000 >++#endif >++ >++#endif /* AP_MPM_DEFAULT_H */ >++/** @} */ >+unchanged: >+--- orig/server/mpm/config.m4 2007-01-29 21:30:26.000000000 +0100 >++++ server/mpm/config.m4 2007-01-29 21:30:35.000000000 +0100 >+@@ -1,7 +1,7 @@ >+ AC_MSG_CHECKING(which MPM to use) >+ AC_ARG_WITH(mpm, >+ APACHE_HELP_STRING(--with-mpm=MPM,Choose the process model for Apache to use. >+- MPM={beos|event|worker|prefork|mpmt_os2}),[ >++ MPM={beos|event|worker|prefork|mpmt_os2|itk}),[ >+ APACHE_MPM=$withval >+ ],[ >+ if test "x$APACHE_MPM" = "x"; then >+@@ -23,7 +23,7 @@ >+ >+ ap_mpm_is_experimental () >+ { >+- if test "$apache_cv_mpm" = "event" ; then >++ if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "itk" ; then >+ return 0 >+ else >+ return 1 >+unchanged: >+--- server/mpm/experimental/itk/config.m4 2007-01-29 21:03:51.000000000 +0100 >++++ server/mpm/experimental/itk/config.m4 2007-01-29 21:03:57.000000000 +0100 >+@@ -1,3 +1,3 @@ >+ if test "$MPM_NAME" = "itk" ; then >+- APACHE_FAST_OUTPUT(server/mpm/$MPM_NAME/Makefile) >++ APACHE_FAST_OUTPUT(server/mpm/$MPM_SUBDIR_NAME/Makefile) >+ fi >+unchanged: >+--- include/http_request.h 2009-03-21 13:03:31.000000000 +0100 >++++ include/http_request.h 2009-03-21 13:03:41.000000000 +0100 >+@@ -12,6 +12,12 @@ >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >++ * >++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@bigfoot.com>. >++ * Licensed under the same terms as the rest of Apache. >++ * >++ * Portions copyright 2008 Knut Auvor Grythe <knut@auvor.no>. >++ * Licensed under the same terms as the rest of Apache. >+ */ >+ >+ /** >+@@ -350,6 +356,15 @@ >+ */ >+ AP_DECLARE_HOOK(void,insert_filter,(request_rec *r)) >+ >++/** >++ * This hook allows modules to affect the request immediately after the >++ * per-directory configuration for the request has been generated. This allows >++ * modules to make decisions based upon the current directory configuration >++ * @param r The current request >++ * @return OK or DECLINED >++ */ >++AP_DECLARE_HOOK(int,post_perdir_config,(request_rec *r)) >++ >+ AP_DECLARE(int) ap_location_walk(request_rec *r); >+ AP_DECLARE(int) ap_directory_walk(request_rec *r); >+ AP_DECLARE(int) ap_file_walk(request_rec *r); >+unchanged: >+--- server/request.c 2009-03-21 13:03:13.000000000 +0100 >++++ server/request.c 2009-03-21 13:03:41.000000000 +0100 >+@@ -12,6 +12,12 @@ >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >++ * >++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@bigfoot.com>. >++ * Licensed under the same terms as the rest of Apache. >++ * >++ * Portions copyright 2008 Knut Auvor Grythe <knut@auvor.no>. >++ * Licensed under the same terms as the rest of Apache. >+ */ >+ >+ /* >+@@ -61,6 +67,7 @@ >+ APR_HOOK_LINK(auth_checker) >+ APR_HOOK_LINK(insert_filter) >+ APR_HOOK_LINK(create_request) >++ APR_HOOK_LINK(post_perdir_config) >+ ) >+ >+ AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name, >+@@ -80,6 +87,8 @@ >+ AP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r)) >+ AP_IMPLEMENT_HOOK_RUN_ALL(int, create_request, >+ (request_rec *r), (r), OK, DECLINED) >++AP_IMPLEMENT_HOOK_RUN_ALL(int,post_perdir_config, >++ (request_rec *r), (r), OK, DECLINED) >+ >+ >+ static int decl_die(int status, char *phase, request_rec *r) >+@@ -158,6 +167,13 @@ >+ return access_status; >+ } >+ >++ /* First chance to handle the request after per-directory configuration is >++ * generated >++ */ >++ if ((access_status = ap_run_post_perdir_config(r))) { >++ return access_status; >++ } >++ >+ /* Only on the main request! */ >+ if (r->main == NULL) { >+ if ((access_status = ap_run_header_parser(r))) { >+unchanged: >+--- server/mpm/config.m4 2009-04-14 23:26:41.000000000 +0200 >++++ server/mpm/config.m4 2009-04-14 23:28:03.000000000 +0200 >+@@ -66,6 +66,11 @@ >+ else >+ MPM_SUBDIR_NAME=$MPM_NAME >+ fi >++ >++if test "$apache_cv_mpm" = "itk" ; then >++ AC_CHECK_LIB(cap, cap_init) >++fi >++ >+ MPM_DIR=server/mpm/$MPM_SUBDIR_NAME >+ MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 137953
: 98964