Gentoo Archives: gentoo-commits

From: "Peter Volkov (pva)" <pva@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] apache r235 - in trunk/dist/2.2: init patches
Date: Thu, 01 Sep 2011 15:34:09
Message-Id: 20110901153353.7934D2004C@flycatcher.gentoo.org
1 Author: pva
2 Date: 2011-09-01 15:33:52 +0000 (Thu, 01 Sep 2011)
3 New Revision: 235
4
5 Added:
6 trunk/dist/2.2/patches/21_all-itk-20110321.patch
7 Removed:
8 trunk/dist/2.2/patches/21_all_itk_20090114.patch
9 Modified:
10 trunk/dist/2.2/init/apache2.initd
11 trunk/dist/2.2/patches/03_all_gentoo_apache-tools.patch
12 trunk/dist/2.2/patches/20_all_peruser_0.4.0-rc2.patch
13 Log:
14 Prepare 2.2.20: update init script to respect return status of stop, bug #357585 wrt Robert Trace; update itk patch, thank Denis Kaganovich for report in bug 368743#c2.
15
16 Modified: trunk/dist/2.2/init/apache2.initd
17 ===================================================================
18 --- trunk/dist/2.2/init/apache2.initd 2011-02-18 17:28:28 UTC (rev 234)
19 +++ trunk/dist/2.2/init/apache2.initd 2011-09-01 15:33:52 UTC (rev 235)
20 @@ -91,7 +91,7 @@
21 sleep 1 && i=$(expr $i + 1)
22 done
23
24 - test $i -le ${TIMEOUT}
25 + test $i -lt ${TIMEOUT}
26 eend $?
27 }
28
29
30 Modified: trunk/dist/2.2/patches/03_all_gentoo_apache-tools.patch
31 ===================================================================
32 --- trunk/dist/2.2/patches/03_all_gentoo_apache-tools.patch 2011-02-18 17:28:28 UTC (rev 234)
33 +++ trunk/dist/2.2/patches/03_all_gentoo_apache-tools.patch 2011-09-01 15:33:52 UTC (rev 235)
34 @@ -1,13 +1,16 @@
35 ----
36 - Makefile.in | 10 ++++++++--
37 - support/Makefile.in | 18 ++++--------------
38 - 2 files changed, 12 insertions(+), 16 deletions(-)
39 -
40 -Index: httpd-2.2.6/Makefile.in
41 -===================================================================
42 ---- httpd-2.2.6.orig/Makefile.in
43 -+++ httpd-2.2.6/Makefile.in
44 -@@ -198,14 +198,20 @@ install-include:
45 +diff -pruN a/Makefile.in b/Makefile.in
46 +--- a/Makefile.in 2011-08-24 00:34:55.000000000 +0300
47 ++++ b/Makefile.in 2011-08-24 00:29:01.000000000 +0300
48 +@@ -14,7 +14,7 @@ PROGRAM_DEPENDENCIES = \
49 +
50 + PROGRAMS = $(PROGRAM_NAME)
51 + TARGETS = $(PROGRAMS) $(shared_build) $(other_targets)
52 +-INSTALL_TARGETS = install-htdocs install-error install-icons \
53 ++INSTALL_TARGETS = install-conf install-htdocs install-error install-icons \
54 + install-other install-cgi install-include install-suexec install-build \
55 + install-man
56 +
57 +@@ -202,14 +202,20 @@ install-include:
58 $(INSTALL_DATA) $$hdr $(DESTDIR)$(includedir); \
59 done
60
61 @@ -30,10 +33,9 @@
62 @if test "x$(RSYNC)" != "x" && test -x $(RSYNC) ; then \
63 $(RSYNC) --exclude .svn -rlpt --numeric-ids $(top_srcdir)/docs/manual/ $(DESTDIR)$(manualdir)/; \
64 else \
65 -Index: httpd-2.2.6/support/Makefile.in
66 -===================================================================
67 ---- httpd-2.2.6.orig/support/Makefile.in
68 -+++ httpd-2.2.6/support/Makefile.in
69 +diff -pruN a/support/Makefile.in b/support/Makefile.in
70 +--- a/support/Makefile.in 2011-04-16 22:09:47.000000000 +0300
71 ++++ b/support/Makefile.in 2011-08-24 00:33:10.000000000 +0300
72 @@ -1,9 +1,8 @@
73 -DISTCLEAN_TARGETS = apxs apachectl dbmmanage log_server_status \
74 - logresolve.pl phf_abuse_log.cgi split-logfile envvars-std
75 @@ -41,12 +43,12 @@
76
77 CLEAN_TARGETS = suexec
78
79 --PROGRAMS = htpasswd htdigest rotatelogs logresolve ab checkgid htdbm htcacheclean httxt2dbm
80 +-PROGRAMS = htpasswd htdigest rotatelogs logresolve ab htdbm htcacheclean httxt2dbm $(NONPORTABLE_SUPPORT)
81 +PROGRAMS = apxs
82 TARGETS = $(PROGRAMS)
83
84 PROGRAM_LDADD = $(UTIL_LDFLAGS) $(PROGRAM_DEPENDENCIES) $(EXTRA_LIBS) $(AP_LIBS)
85 -@@ -12,22 +11,13 @@ PROGRAM_DEPENDENCIES =
86 +@@ -12,22 +11,13 @@ PROGRAM_DEPENDENCIES =
87 include $(top_builddir)/build/rules.mk
88
89 install:
90
91 Modified: trunk/dist/2.2/patches/20_all_peruser_0.4.0-rc2.patch
92 ===================================================================
93 --- trunk/dist/2.2/patches/20_all_peruser_0.4.0-rc2.patch 2011-02-18 17:28:28 UTC (rev 234)
94 +++ trunk/dist/2.2/patches/20_all_peruser_0.4.0-rc2.patch 2011-09-01 15:33:52 UTC (rev 235)
95 @@ -123,8 +123,8 @@
96 AC_MSG_CHECKING(which MPM to use)
97 AC_ARG_WITH(mpm,
98 APACHE_HELP_STRING(--with-mpm=MPM,Choose the process model for Apache to use.
99 -- MPM={beos|event|worker|prefork|mpmt_os2}),[
100 -+ MPM={beos|event|worker|prefork|mpmt_os2|peruser}),[
101 +- MPM={beos|event|worker|prefork|mpmt_os2|winnt}),[
102 ++ MPM={beos|event|worker|prefork|mpmt_os2|winnt|peruser}),[
103 APACHE_MPM=$withval
104 ],[
105 if test "x$APACHE_MPM" = "x"; then
106
107 Copied: trunk/dist/2.2/patches/21_all-itk-20110321.patch (from rev 234, trunk/dist/2.2/patches/21_all_itk_20090114.patch)
108 ===================================================================
109 --- trunk/dist/2.2/patches/21_all-itk-20110321.patch (rev 0)
110 +++ trunk/dist/2.2/patches/21_all-itk-20110321.patch 2011-09-01 15:33:52 UTC (rev 235)
111 @@ -0,0 +1,2084 @@
112 +unchanged:
113 +--- httpd-2.2.17/server/mpm/experimental/itk/Makefile.in
114 ++++ httpd-2.2.17/server/mpm/experimental/itk/Makefile.in
115 +@@ -0,0 +1,5 @@
116 ++
117 ++LTLIBRARY_NAME = libitk.la
118 ++LTLIBRARY_SOURCES = itk.c
119 ++
120 ++include $(top_srcdir)/build/ltlib.mk
121 +unchanged:
122 +--- httpd-2.2.17/server/mpm/experimental/itk/config.m4
123 ++++ httpd-2.2.17/server/mpm/experimental/itk/config.m4
124 +@@ -0,0 +1,3 @@
125 ++if test "$MPM_NAME" = "itk" ; then
126 ++ APACHE_FAST_OUTPUT(server/mpm/$MPM_SUBDIR_NAME/Makefile)
127 ++fi
128 +unchanged:
129 +--- httpd-2.2.17/server/mpm/experimental/itk/itk.c
130 ++++ httpd-2.2.17/server/mpm/experimental/itk/itk.c
131 +@@ -0,0 +1,1757 @@
132 ++/* Licensed to the Apache Software Foundation (ASF) under one or more
133 ++ * contributor license agreements. See the NOTICE file distributed with
134 ++ * this work for additional information regarding copyright ownership.
135 ++ * The ASF licenses this file to You under the Apache License, Version 2.0
136 ++ * (the "License"); you may not use this file except in compliance with
137 ++ * the License. You may obtain a copy of the License at
138 ++ *
139 ++ * http://www.apache.org/licenses/LICENSE-2.0
140 ++ *
141 ++ * Unless required by applicable law or agreed to in writing, software
142 ++ * distributed under the License is distributed on an "AS IS" BASIS,
143 ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144 ++ * See the License for the specific language governing permissions and
145 ++ * limitations under the License.
146 ++ *
147 ++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
148 ++ * Licensed under the same terms as the rest of Apache.
149 ++ *
150 ++ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
151 ++ * Licensed under the same terms as the rest of Apache.
152 ++ */
153 ++
154 ++#include "apr.h"
155 ++#include "apr_portable.h"
156 ++#include "apr_strings.h"
157 ++#include "apr_thread_proc.h"
158 ++#include "apr_signal.h"
159 ++
160 ++# define _DBG(text,par...) \
161 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \
162 ++ "(itkmpm: pid=%d uid=%d, gid=%d) %s(): " text, \
163 ++ getpid(), getuid(), getgid(), __FUNCTION__, par)
164 ++
165 ++#define APR_WANT_STDIO
166 ++#define APR_WANT_STRFUNC
167 ++#include "apr_want.h"
168 ++
169 ++#if APR_HAVE_UNISTD_H
170 ++#include <unistd.h>
171 ++#endif
172 ++#if APR_HAVE_SYS_TYPES_H
173 ++#include <sys/types.h>
174 ++#endif
175 ++
176 ++#define CORE_PRIVATE
177 ++
178 ++#include "ap_config.h"
179 ++#include "httpd.h"
180 ++#include "mpm_default.h"
181 ++#include "http_main.h"
182 ++#include "http_log.h"
183 ++#include "http_config.h"
184 ++#include "http_core.h" /* for get_remote_host */
185 ++#include "http_connection.h"
186 ++#include "http_request.h" /* for ap_hook_post_perdir_config */
187 ++#include "scoreboard.h"
188 ++#include "ap_mpm.h"
189 ++#include "unixd.h"
190 ++#include "mpm_common.h"
191 ++#include "ap_listen.h"
192 ++#include "ap_mmn.h"
193 ++#include "apr_poll.h"
194 ++
195 ++#ifdef HAVE_BSTRING_H
196 ++#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
197 ++#endif
198 ++#ifdef HAVE_TIME_H
199 ++#include <time.h>
200 ++#endif
201 ++#ifdef HAVE_SYS_PROCESSOR_H
202 ++#include <sys/processor.h> /* for bindprocessor() */
203 ++#endif
204 ++
205 ++#if HAVE_LIBCAP
206 ++#include <sys/capability.h>
207 ++#endif
208 ++
209 ++#include <signal.h>
210 ++#include <sys/times.h>
211 ++
212 ++/* Limit on the total --- clients will be locked out if more servers than
213 ++ * this are needed. It is intended solely to keep the server from crashing
214 ++ * when things get out of hand.
215 ++ *
216 ++ * We keep a hard maximum number of servers, for two reasons --- first off,
217 ++ * in case something goes seriously wrong, we want to stop the fork bomb
218 ++ * short of actually crashing the machine we're running on by filling some
219 ++ * kernel table. Secondly, it keeps the size of the scoreboard file small
220 ++ * enough that we can read the whole thing without worrying too much about
221 ++ * the overhead.
222 ++ */
223 ++#ifndef DEFAULT_SERVER_LIMIT
224 ++#define DEFAULT_SERVER_LIMIT 256
225 ++#endif
226 ++
227 ++/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
228 ++ * some sort of compile-time limit to help catch typos.
229 ++ */
230 ++#ifndef MAX_SERVER_LIMIT
231 ++#define MAX_SERVER_LIMIT 200000
232 ++#endif
233 ++
234 ++#ifndef HARD_THREAD_LIMIT
235 ++#define HARD_THREAD_LIMIT 1
236 ++#endif
237 ++
238 ++/* config globals */
239 ++
240 ++int ap_threads_per_child=0; /* Worker threads per child */
241 ++static apr_proc_mutex_t *accept_mutex;
242 ++static int ap_daemons_to_start=0;
243 ++static int ap_daemons_min_free=0;
244 ++static int ap_daemons_max_free=0;
245 ++static int ap_daemons_limit=0; /* MaxClients */
246 ++static int server_limit = DEFAULT_SERVER_LIMIT;
247 ++static int first_server_limit = 0;
248 ++static int changed_limit_at_restart;
249 ++static int mpm_state = AP_MPMQ_STARTING;
250 ++static ap_pod_t *pod;
251 ++
252 ++/*
253 ++ * The max child slot ever assigned, preserved across restarts. Necessary
254 ++ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
255 ++ * use this value to optimize routines that have to scan the entire scoreboard.
256 ++ */
257 ++int ap_max_daemons_limit = -1;
258 ++server_rec *ap_server_conf;
259 ++
260 ++/* one_process --- debugging mode variable; can be set from the command line
261 ++ * with the -X flag. If set, this gets you the child_main loop running
262 ++ * in the process which originally started up (no detach, no make_child),
263 ++ * which is a pretty nice debugging environment. (You'll get a SIGHUP
264 ++ * early in standalone_main; just continue through. This is the server
265 ++ * trying to kill off any child processes which it might have lying
266 ++ * around --- Apache doesn't keep track of their pids, it just sends
267 ++ * SIGHUP to the process group, ignoring it in the root process.
268 ++ * Continue through and you'll be fine.).
269 ++ */
270 ++
271 ++static int one_process = 0;
272 ++
273 ++static apr_pool_t *pconf; /* Pool for config stuff */
274 ++static apr_pool_t *pchild; /* Pool for httpd child stuff */
275 ++
276 ++static pid_t ap_my_pid; /* it seems silly to call getpid all the time */
277 ++static pid_t parent_pid;
278 ++#ifndef MULTITHREAD
279 ++static int my_child_num;
280 ++#endif
281 ++ap_generation_t volatile ap_my_generation=0;
282 ++
283 ++#ifdef TPF
284 ++int tpf_child = 0;
285 ++char tpf_server_name[INETD_SERVNAME_LENGTH+1];
286 ++#endif /* TPF */
287 ++
288 ++static volatile int die_now = 0;
289 ++
290 ++#define UNSET_NICE_VALUE 100
291 ++
292 ++typedef struct
293 ++{
294 ++ uid_t uid;
295 ++ gid_t gid;
296 ++ char *username;
297 ++ int nice_value;
298 ++} itk_per_dir_conf;
299 ++
300 ++typedef struct
301 ++{
302 ++ int max_clients_vhost;
303 ++} itk_server_conf;
304 ++
305 ++module AP_MODULE_DECLARE_DATA mpm_itk_module;
306 ++
307 ++#ifdef GPROF
308 ++/*
309 ++ * change directory for gprof to plop the gmon.out file
310 ++ * configure in httpd.conf:
311 ++ * GprofDir $RuntimeDir/ -> $ServerRoot/$RuntimeDir/gmon.out
312 ++ * GprofDir $RuntimeDir/% -> $ServerRoot/$RuntimeDir/gprof.$pid/gmon.out
313 ++ */
314 ++static void chdir_for_gprof(void)
315 ++{
316 ++ core_server_config *sconf =
317 ++ ap_get_module_config(ap_server_conf->module_config, &core_module);
318 ++ char *dir = sconf->gprof_dir;
319 ++ const char *use_dir;
320 ++
321 ++ if(dir) {
322 ++ apr_status_t res;
323 ++ char *buf = NULL ;
324 ++ int len = strlen(sconf->gprof_dir) - 1;
325 ++ if(*(dir + len) == '%') {
326 ++ dir[len] = '\0';
327 ++ buf = ap_append_pid(pconf, dir, "gprof.");
328 ++ }
329 ++ use_dir = ap_server_root_relative(pconf, buf ? buf : dir);
330 ++ res = apr_dir_make(use_dir,
331 ++ APR_UREAD | APR_UWRITE | APR_UEXECUTE |
332 ++ APR_GREAD | APR_GEXECUTE |
333 ++ APR_WREAD | APR_WEXECUTE, pconf);
334 ++ if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) {
335 ++ ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf,
336 ++ "gprof: error creating directory %s", dir);
337 ++ }
338 ++ }
339 ++ else {
340 ++ use_dir = ap_server_root_relative(pconf, DEFAULT_REL_RUNTIMEDIR);
341 ++ }
342 ++
343 ++ chdir(use_dir);
344 ++}
345 ++#else
346 ++#define chdir_for_gprof()
347 ++#endif
348 ++
349 ++/* XXX - I don't know if TPF will ever use this module or not, so leave
350 ++ * the ap_check_signals calls in but disable them - manoj */
351 ++#define ap_check_signals()
352 ++
353 ++/* a clean exit from a child with proper cleanup */
354 ++static void clean_child_exit(int code) __attribute__ ((noreturn));
355 ++static void clean_child_exit(int code)
356 ++{
357 ++ mpm_state = AP_MPMQ_STOPPING;
358 ++
359 ++ if (pchild) {
360 ++ apr_pool_destroy(pchild);
361 ++ }
362 ++ ap_mpm_pod_close(pod);
363 ++ chdir_for_gprof();
364 ++ exit(code);
365 ++}
366 ++
367 ++static void accept_mutex_on(void)
368 ++{
369 ++ apr_status_t rv = apr_proc_mutex_lock(accept_mutex);
370 ++ if (rv != APR_SUCCESS) {
371 ++ const char *msg = "couldn't grab the accept mutex";
372 ++
373 ++ if (ap_my_generation !=
374 ++ ap_scoreboard_image->global->running_generation) {
375 ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
376 ++ clean_child_exit(0);
377 ++ }
378 ++ else {
379 ++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
380 ++ exit(APEXIT_CHILDFATAL);
381 ++ }
382 ++ }
383 ++}
384 ++
385 ++static void accept_mutex_off(void)
386 ++{
387 ++ apr_status_t rv = apr_proc_mutex_unlock(accept_mutex);
388 ++ if (rv != APR_SUCCESS) {
389 ++ const char *msg = "couldn't release the accept mutex";
390 ++
391 ++ if (ap_my_generation !=
392 ++ ap_scoreboard_image->global->running_generation) {
393 ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
394 ++ /* don't exit here... we have a connection to
395 ++ * process, after which point we'll see that the
396 ++ * generation changed and we'll exit cleanly
397 ++ */
398 ++ }
399 ++ else {
400 ++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
401 ++ exit(APEXIT_CHILDFATAL);
402 ++ }
403 ++ }
404 ++}
405 ++
406 ++/* On some architectures it's safe to do unserialized accept()s in the single
407 ++ * Listen case. But it's never safe to do it in the case where there's
408 ++ * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
409 ++ * when it's safe in the single Listen case.
410 ++ */
411 ++#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
412 ++#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
413 ++#else
414 ++#define SAFE_ACCEPT(stmt) do {stmt;} while(0)
415 ++#endif
416 ++
417 ++AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
418 ++{
419 ++ switch(query_code){
420 ++ case AP_MPMQ_MAX_DAEMON_USED:
421 ++ *result = ap_daemons_limit;
422 ++ return APR_SUCCESS;
423 ++ case AP_MPMQ_IS_THREADED:
424 ++ *result = AP_MPMQ_NOT_SUPPORTED;
425 ++ return APR_SUCCESS;
426 ++ case AP_MPMQ_IS_FORKED:
427 ++ *result = AP_MPMQ_DYNAMIC;
428 ++ return APR_SUCCESS;
429 ++ case AP_MPMQ_HARD_LIMIT_DAEMONS:
430 ++ *result = server_limit;
431 ++ return APR_SUCCESS;
432 ++ case AP_MPMQ_HARD_LIMIT_THREADS:
433 ++ *result = HARD_THREAD_LIMIT;
434 ++ return APR_SUCCESS;
435 ++ case AP_MPMQ_MAX_THREADS:
436 ++ *result = 0;
437 ++ return APR_SUCCESS;
438 ++ case AP_MPMQ_MIN_SPARE_DAEMONS:
439 ++ *result = ap_daemons_min_free;
440 ++ return APR_SUCCESS;
441 ++ case AP_MPMQ_MIN_SPARE_THREADS:
442 ++ *result = 0;
443 ++ return APR_SUCCESS;
444 ++ case AP_MPMQ_MAX_SPARE_DAEMONS:
445 ++ *result = ap_daemons_max_free;
446 ++ return APR_SUCCESS;
447 ++ case AP_MPMQ_MAX_SPARE_THREADS:
448 ++ *result = 0;
449 ++ return APR_SUCCESS;
450 ++ case AP_MPMQ_MAX_REQUESTS_DAEMON:
451 ++ *result = ap_max_requests_per_child;
452 ++ return APR_SUCCESS;
453 ++ case AP_MPMQ_MAX_DAEMONS:
454 ++ *result = server_limit;
455 ++ return APR_SUCCESS;
456 ++ case AP_MPMQ_MPM_STATE:
457 ++ *result = mpm_state;
458 ++ return APR_SUCCESS;
459 ++ }
460 ++ return APR_ENOTIMPL;
461 ++}
462 ++
463 ++#if defined(NEED_WAITPID)
464 ++/*
465 ++ Systems without a real waitpid sometimes lose a child's exit while waiting
466 ++ for another. Search through the scoreboard for missing children.
467 ++ */
468 ++int reap_children(int *exitcode, apr_exit_why_e *status)
469 ++{
470 ++ int n, pid;
471 ++
472 ++ for (n = 0; n < ap_max_daemons_limit; ++n) {
473 ++ if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&
474 ++ kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
475 ++ ap_update_child_status_from_indexes(n, 0, SERVER_DEAD, NULL);
476 ++ /* just mark it as having a successful exit status */
477 ++ *status = APR_PROC_EXIT;
478 ++ *exitcode = 0;
479 ++ return(pid);
480 ++ }
481 ++ }
482 ++ return 0;
483 ++}
484 ++#endif
485 ++
486 ++/*****************************************************************
487 ++ * Connection structures and accounting...
488 ++ */
489 ++
490 ++static void just_die(int sig)
491 ++{
492 ++ clean_child_exit(0);
493 ++}
494 ++
495 ++static void stop_listening(int sig)
496 ++{
497 ++ ap_close_listeners();
498 ++
499 ++ /* For a graceful stop, we want the child to exit when done */
500 ++ die_now = 1;
501 ++}
502 ++
503 ++/* volatile just in case */
504 ++static int volatile shutdown_pending;
505 ++static int volatile restart_pending;
506 ++static int volatile is_graceful;
507 ++
508 ++static void sig_term(int sig)
509 ++{
510 ++ if (shutdown_pending == 1) {
511 ++ /* Um, is this _probably_ not an error, if the user has
512 ++ * tried to do a shutdown twice quickly, so we won't
513 ++ * worry about reporting it.
514 ++ */
515 ++ return;
516 ++ }
517 ++ shutdown_pending = 1;
518 ++ is_graceful = (sig == AP_SIG_GRACEFUL_STOP);
519 ++}
520 ++
521 ++/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL
522 ++ * in the parent process, unless running in ONE_PROCESS mode
523 ++ */
524 ++static void restart(int sig)
525 ++{
526 ++ if (restart_pending == 1) {
527 ++ /* Probably not an error - don't bother reporting it */
528 ++ return;
529 ++ }
530 ++ restart_pending = 1;
531 ++ is_graceful = (sig == AP_SIG_GRACEFUL);
532 ++}
533 ++
534 ++static void set_signals(void)
535 ++{
536 ++#ifndef NO_USE_SIGACTION
537 ++ struct sigaction sa;
538 ++#endif
539 ++
540 ++ if (!one_process) {
541 ++ ap_fatal_signal_setup(ap_server_conf, pconf);
542 ++ }
543 ++
544 ++#ifndef NO_USE_SIGACTION
545 ++ sigemptyset(&sa.sa_mask);
546 ++ sa.sa_flags = 0;
547 ++
548 ++ sa.sa_handler = sig_term;
549 ++ if (sigaction(SIGTERM, &sa, NULL) < 0)
550 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
551 ++#ifdef AP_SIG_GRACEFUL_STOP
552 ++ if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
553 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
554 ++ "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
555 ++#endif
556 ++#ifdef SIGINT
557 ++ if (sigaction(SIGINT, &sa, NULL) < 0)
558 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
559 ++#endif
560 ++#ifdef SIGXCPU
561 ++ sa.sa_handler = SIG_DFL;
562 ++ if (sigaction(SIGXCPU, &sa, NULL) < 0)
563 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
564 ++#endif
565 ++#ifdef SIGXFSZ
566 ++ sa.sa_handler = SIG_DFL;
567 ++ if (sigaction(SIGXFSZ, &sa, NULL) < 0)
568 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
569 ++#endif
570 ++#ifdef SIGPIPE
571 ++ sa.sa_handler = SIG_IGN;
572 ++ if (sigaction(SIGPIPE, &sa, NULL) < 0)
573 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
574 ++#endif
575 ++
576 ++ /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
577 ++ * processing one
578 ++ */
579 ++ sigaddset(&sa.sa_mask, SIGHUP);
580 ++ sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
581 ++ sa.sa_handler = restart;
582 ++ if (sigaction(SIGHUP, &sa, NULL) < 0)
583 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
584 ++ if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
585 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")");
586 ++#else
587 ++ if (!one_process) {
588 ++#ifdef SIGXCPU
589 ++ apr_signal(SIGXCPU, SIG_DFL);
590 ++#endif /* SIGXCPU */
591 ++#ifdef SIGXFSZ
592 ++ apr_signal(SIGXFSZ, SIG_DFL);
593 ++#endif /* SIGXFSZ */
594 ++ }
595 ++
596 ++ apr_signal(SIGTERM, sig_term);
597 ++#ifdef SIGHUP
598 ++ apr_signal(SIGHUP, restart);
599 ++#endif /* SIGHUP */
600 ++#ifdef AP_SIG_GRACEFUL
601 ++ apr_signal(AP_SIG_GRACEFUL, restart);
602 ++#endif /* AP_SIG_GRACEFUL */
603 ++#ifdef AP_SIG_GRACEFUL_STOP
604 ++ apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
605 ++#endif /* AP_SIG_GRACEFUL */
606 ++#ifdef SIGPIPE
607 ++ apr_signal(SIGPIPE, SIG_IGN);
608 ++#endif /* SIGPIPE */
609 ++
610 ++#endif
611 ++}
612 ++
613 ++/*****************************************************************
614 ++ * Child process main loop.
615 ++ * The following vars are static to avoid getting clobbered by longjmp();
616 ++ * they are really private to child_main.
617 ++ */
618 ++
619 ++static int requests_this_child;
620 ++static int num_listensocks = 0;
621 ++
622 ++
623 ++int ap_graceful_stop_signalled(void)
624 ++{
625 ++ /* not ever called anymore... */
626 ++ return 0;
627 ++}
628 ++
629 ++
630 ++static void child_main(int child_num_arg)
631 ++{
632 ++ apr_pool_t *ptrans;
633 ++ apr_allocator_t *allocator;
634 ++ apr_status_t status;
635 ++ int i;
636 ++ ap_listen_rec *lr;
637 ++ apr_pollset_t *pollset;
638 ++ ap_sb_handle_t *sbh;
639 ++ apr_bucket_alloc_t *bucket_alloc;
640 ++ int last_poll_idx = 0;
641 ++
642 ++#if HAVE_LIBCAP
643 ++ cap_t caps;
644 ++ cap_value_t suidcaps[] = {
645 ++ CAP_SETUID,
646 ++ CAP_SETGID,
647 ++ CAP_DAC_READ_SEARCH,
648 ++ CAP_SYS_NICE,
649 ++ };
650 ++#endif
651 ++
652 ++ mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
653 ++ * child initializes
654 ++ */
655 ++
656 ++ my_child_num = child_num_arg;
657 ++ ap_my_pid = getpid();
658 ++ requests_this_child = 0;
659 ++
660 ++ ap_fatal_signal_child_setup(ap_server_conf);
661 ++
662 ++ /* Get a sub context for global allocations in this child, so that
663 ++ * we can have cleanups occur when the child exits.
664 ++ */
665 ++ apr_allocator_create(&allocator);
666 ++ apr_allocator_max_free_set(allocator, ap_max_mem_free);
667 ++ apr_pool_create_ex(&pchild, pconf, NULL, allocator);
668 ++ apr_allocator_owner_set(allocator, pchild);
669 ++
670 ++ apr_pool_create(&ptrans, pchild);
671 ++ apr_pool_tag(ptrans, "transaction");
672 ++
673 ++ /* needs to be done before we switch UIDs so we have permissions */
674 ++ ap_reopen_scoreboard(pchild, NULL, 0);
675 ++ status = apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild);
676 ++ if (status != APR_SUCCESS) {
677 ++ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,
678 ++ "Couldn't initialize cross-process lock in child "
679 ++ "(%s) (%d)", ap_lock_fname, ap_accept_lock_mech);
680 ++ clean_child_exit(APEXIT_CHILDFATAL);
681 ++ }
682 ++
683 ++ ap_run_child_init(pchild, ap_server_conf);
684 ++
685 ++ ap_create_sb_handle(&sbh, pchild, my_child_num, 0);
686 ++
687 ++ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
688 ++
689 ++ /* Set up the pollfd array */
690 ++ status = apr_pollset_create(&pollset, num_listensocks, pchild, 0);
691 ++ if (status != APR_SUCCESS) {
692 ++ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,
693 ++ "Couldn't create pollset in child; check system or user limits");
694 ++ clean_child_exit(APEXIT_CHILDSICK); /* assume temporary resource issue */
695 ++ }
696 ++
697 ++ for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) {
698 ++ apr_pollfd_t pfd = { 0 };
699 ++
700 ++ pfd.desc_type = APR_POLL_SOCKET;
701 ++ pfd.desc.s = lr->sd;
702 ++ pfd.reqevents = APR_POLLIN;
703 ++ pfd.client_data = lr;
704 ++
705 ++ /* ### check the status */
706 ++ (void) apr_pollset_add(pollset, &pfd);
707 ++ }
708 ++
709 ++#if HAVE_LIBCAP
710 ++ /* Drop as many privileges as we can. We'll still
711 ++ * access files with uid=0, and we can setuid() to anything, but
712 ++ * at least there's tons of other evilness (like loading kernel
713 ++ * modules) we can't do directly. (The setuid() capability will
714 ++ * go away automatically when we setuid() or exec() -- the former
715 ++ * is likely to come first.)
716 ++ */
717 ++ caps = cap_init();
718 ++ cap_clear(caps);
719 ++ cap_set_flag(caps, CAP_PERMITTED, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET);
720 ++ cap_set_flag(caps, CAP_EFFECTIVE, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET);
721 ++ cap_set_proc(caps);
722 ++ cap_free(caps);
723 ++#endif
724 ++
725 ++ mpm_state = AP_MPMQ_RUNNING;
726 ++
727 ++ bucket_alloc = apr_bucket_alloc_create(pchild);
728 ++
729 ++ /* die_now is set when AP_SIG_GRACEFUL is received in the child;
730 ++ * shutdown_pending is set when SIGTERM is received when running
731 ++ * in single process mode. */
732 ++ while (!die_now && !shutdown_pending) {
733 ++ conn_rec *current_conn;
734 ++ void *csd;
735 ++
736 ++ /*
737 ++ * (Re)initialize this child to a pre-connection state.
738 ++ */
739 ++
740 ++ apr_pool_clear(ptrans);
741 ++
742 ++ if ((ap_max_requests_per_child > 0
743 ++ && requests_this_child++ >= ap_max_requests_per_child)) {
744 ++ clean_child_exit(0);
745 ++ }
746 ++
747 ++ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
748 ++
749 ++ /*
750 ++ * Wait for an acceptable connection to arrive.
751 ++ */
752 ++
753 ++ /* Lock around "accept", if necessary */
754 ++ SAFE_ACCEPT(accept_mutex_on());
755 ++
756 ++ if (num_listensocks == 1) {
757 ++ /* There is only one listener record, so refer to that one. */
758 ++ lr = ap_listeners;
759 ++ }
760 ++ else {
761 ++ /* multiple listening sockets - need to poll */
762 ++ for (;;) {
763 ++ apr_int32_t numdesc;
764 ++ const apr_pollfd_t *pdesc;
765 ++
766 ++ /* check for termination first so we don't sleep for a while in
767 ++ * poll if already signalled
768 ++ */
769 ++ if (one_process && shutdown_pending) {
770 ++ SAFE_ACCEPT(accept_mutex_off());
771 ++ return;
772 ++ }
773 ++ else if (die_now) {
774 ++ /* In graceful stop/restart; drop the mutex
775 ++ * and terminate the child. */
776 ++ SAFE_ACCEPT(accept_mutex_off());
777 ++ clean_child_exit(0);
778 ++ }
779 ++ /* timeout == 10 seconds to avoid a hang at graceful restart/stop
780 ++ * caused by the closing of sockets by the signal handler
781 ++ */
782 ++ status = apr_pollset_poll(pollset, apr_time_from_sec(10),
783 ++ &numdesc, &pdesc);
784 ++ if (status != APR_SUCCESS) {
785 ++ if (APR_STATUS_IS_TIMEUP(status) ||
786 ++ APR_STATUS_IS_EINTR(status)) {
787 ++ continue;
788 ++ }
789 ++ /* Single Unix documents select as returning errnos
790 ++ * EBADF, EINTR, and EINVAL... and in none of those
791 ++ * cases does it make sense to continue. In fact
792 ++ * on Linux 2.0.x we seem to end up with EFAULT
793 ++ * occasionally, and we'd loop forever due to it.
794 ++ */
795 ++ ap_log_error(APLOG_MARK, APLOG_ERR, status,
796 ++ ap_server_conf, "apr_pollset_poll: (listen)");
797 ++ SAFE_ACCEPT(accept_mutex_off());
798 ++ clean_child_exit(1);
799 ++ }
800 ++
801 ++ /* We can always use pdesc[0], but sockets at position N
802 ++ * could end up completely starved of attention in a very
803 ++ * busy server. Therefore, we round-robin across the
804 ++ * returned set of descriptors. While it is possible that
805 ++ * the returned set of descriptors might flip around and
806 ++ * continue to starve some sockets, we happen to know the
807 ++ * internal pollset implementation retains ordering
808 ++ * stability of the sockets. Thus, the round-robin should
809 ++ * ensure that a socket will eventually be serviced.
810 ++ */
811 ++ if (last_poll_idx >= numdesc)
812 ++ last_poll_idx = 0;
813 ++
814 ++ /* Grab a listener record from the client_data of the poll
815 ++ * descriptor, and advance our saved index to round-robin
816 ++ * the next fetch.
817 ++ *
818 ++ * ### hmm... this descriptor might have POLLERR rather
819 ++ * ### than POLLIN
820 ++ */
821 ++ lr = pdesc[last_poll_idx++].client_data;
822 ++ goto got_fd;
823 ++ }
824 ++ }
825 ++ got_fd:
826 ++ /* if we accept() something we don't want to die, so we have to
827 ++ * defer the exit
828 ++ */
829 ++ status = lr->accept_func(&csd, lr, ptrans);
830 ++
831 ++ SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
832 ++
833 ++ if (status == APR_EGENERAL) {
834 ++ /* resource shortage or should-not-occur occured */
835 ++ clean_child_exit(1);
836 ++ }
837 ++ else if (status != APR_SUCCESS) {
838 ++ continue;
839 ++ }
840 ++
841 ++ /*
842 ++ * We now have a connection, so set it up with the appropriate
843 ++ * socket options, file descriptors, and read/write buffers.
844 ++ */
845 ++
846 ++ {
847 ++ pid_t pid = fork(), child_pid;
848 ++ int status;
849 ++ switch (pid) {
850 ++ case -1:
851 ++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "fork: Unable to fork new process");
852 ++ break;
853 ++ case 0: /* child */
854 ++ apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild);
855 ++ current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc);
856 ++ if (current_conn) {
857 ++ ap_process_connection(current_conn, csd);
858 ++ ap_lingering_close(current_conn);
859 ++ }
860 ++ exit(0);
861 ++ default: /* parent; just wait for child to be done */
862 ++ do {
863 ++ child_pid = waitpid(pid, &status, 0);
864 ++ } while (child_pid == -1 && errno == EINTR);
865 ++
866 ++ if (child_pid != pid || !WIFEXITED(status)) {
867 ++ if (WIFSIGNALED(status)) {
868 ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child died with signal %u", WTERMSIG(status));
869 ++ } else if (WEXITSTATUS(status) != 0) {
870 ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child exited with non-zero exit status %u", WEXITSTATUS(status));
871 ++ } else {
872 ++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "waitpid() failed");
873 ++ }
874 ++ clean_child_exit(1);
875 ++ }
876 ++ break;
877 ++ }
878 ++ }
879 ++
880 ++ /* Check the pod and the generation number after processing a
881 ++ * connection so that we'll go away if a graceful restart occurred
882 ++ * while we were processing the connection or we are the lucky
883 ++ * idle server process that gets to die.
884 ++ */
885 ++ if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */
886 ++ die_now = 1;
887 ++ }
888 ++ else if (ap_my_generation !=
889 ++ ap_scoreboard_image->global->running_generation) { /* restart? */
890 ++ /* yeah, this could be non-graceful restart, in which case the
891 ++ * parent will kill us soon enough, but why bother checking?
892 ++ */
893 ++ die_now = 1;
894 ++ }
895 ++
896 ++ /* if we have already setuid(), die (we can't be used anyhow) */
897 ++ if (getuid())
898 ++ die_now = 1;
899 ++ }
900 ++ /* This apr_pool_clear call is redundant, should be redundant, but compensates
901 ++ * a flaw in the apr reslist code. This should be removed once that flaw has
902 ++ * been addressed.
903 ++ */
904 ++ apr_pool_clear(ptrans);
905 ++ clean_child_exit(0);
906 ++}
907 ++
908 ++
909 ++static int make_child(server_rec *s, int slot)
910 ++{
911 ++ int pid;
912 ++
913 ++ if (slot + 1 > ap_max_daemons_limit) {
914 ++ ap_max_daemons_limit = slot + 1;
915 ++ }
916 ++
917 ++ if (one_process) {
918 ++ apr_signal(SIGHUP, sig_term);
919 ++ /* Don't catch AP_SIG_GRACEFUL in ONE_PROCESS mode :) */
920 ++ apr_signal(SIGINT, sig_term);
921 ++#ifdef SIGQUIT
922 ++ apr_signal(SIGQUIT, SIG_DFL);
923 ++#endif
924 ++ apr_signal(SIGTERM, sig_term);
925 ++ child_main(slot);
926 ++ return 0;
927 ++ }
928 ++
929 ++ (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING,
930 ++ (request_rec *) NULL);
931 ++
932 ++
933 ++#ifdef _OSD_POSIX
934 ++ /* BS2000 requires a "special" version of fork() before a setuid() call */
935 ++ if ((pid = os_fork(unixd_config.user_name)) == -1) {
936 ++#elif defined(TPF)
937 ++ if ((pid = os_fork(s, slot)) == -1) {
938 ++#else
939 ++ if ((pid = fork()) == -1) {
940 ++#endif
941 ++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
942 ++
943 ++ /* fork didn't succeed. Fix the scoreboard or else
944 ++ * it will say SERVER_STARTING forever and ever
945 ++ */
946 ++ (void) ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD,
947 ++ (request_rec *) NULL);
948 ++
949 ++ /* In case system resources are maxxed out, we don't want
950 ++ * Apache running away with the CPU trying to fork over and
951 ++ * over and over again.
952 ++ */
953 ++ sleep(10);
954 ++
955 ++ return -1;
956 ++ }
957 ++
958 ++ if (!pid) {
959 ++#ifdef HAVE_BINDPROCESSOR
960 ++ /* by default AIX binds to a single processor
961 ++ * this bit unbinds children which will then bind to another cpu
962 ++ */
963 ++ int status = bindprocessor(BINDPROCESS, (int)getpid(),
964 ++ PROCESSOR_CLASS_ANY);
965 ++ if (status != OK) {
966 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
967 ++ ap_server_conf, "processor unbind failed %d", status);
968 ++ }
969 ++#endif
970 ++ RAISE_SIGSTOP(MAKE_CHILD);
971 ++ AP_MONCONTROL(1);
972 ++ /* Disable the parent's signal handlers and set up proper handling in
973 ++ * the child.
974 ++ */
975 ++ apr_signal(SIGHUP, just_die);
976 ++ apr_signal(SIGTERM, just_die);
977 ++ /* The child process just closes listeners on AP_SIG_GRACEFUL.
978 ++ * The pod is used for signalling the graceful restart.
979 ++ */
980 ++ apr_signal(AP_SIG_GRACEFUL, stop_listening);
981 ++ child_main(slot);
982 ++ }
983 ++
984 ++ ap_scoreboard_image->parent[slot].pid = pid;
985 ++
986 ++ return 0;
987 ++}
988 ++
989 ++
990 ++/* start up a bunch of children */
991 ++static void startup_children(int number_to_start)
992 ++{
993 ++ int i;
994 ++
995 ++ for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
996 ++ if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
997 ++ continue;
998 ++ }
999 ++ if (make_child(ap_server_conf, i) < 0) {
1000 ++ break;
1001 ++ }
1002 ++ --number_to_start;
1003 ++ }
1004 ++}
1005 ++
1006 ++
1007 ++/*
1008 ++ * idle_spawn_rate is the number of children that will be spawned on the
1009 ++ * next maintenance cycle if there aren't enough idle servers. It is
1010 ++ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
1011 ++ * without the need to spawn.
1012 ++ */
1013 ++static int idle_spawn_rate = 1;
1014 ++#ifndef MAX_SPAWN_RATE
1015 ++#define MAX_SPAWN_RATE (32)
1016 ++#endif
1017 ++static int hold_off_on_exponential_spawning;
1018 ++
1019 ++static void perform_idle_server_maintenance(apr_pool_t *p)
1020 ++{
1021 ++ int i;
1022 ++ int to_kill;
1023 ++ int idle_count;
1024 ++ worker_score *ws;
1025 ++ int free_length;
1026 ++ int free_slots[MAX_SPAWN_RATE];
1027 ++ int last_non_dead;
1028 ++ int total_non_dead;
1029 ++
1030 ++ /* initialize the free_list */
1031 ++ free_length = 0;
1032 ++
1033 ++ to_kill = -1;
1034 ++ idle_count = 0;
1035 ++ last_non_dead = -1;
1036 ++ total_non_dead = 0;
1037 ++
1038 ++ for (i = 0; i < ap_daemons_limit; ++i) {
1039 ++ int status;
1040 ++
1041 ++ if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
1042 ++ break;
1043 ++ ws = &ap_scoreboard_image->servers[i][0];
1044 ++ status = ws->status;
1045 ++ if (status == SERVER_DEAD) {
1046 ++ /* try to keep children numbers as low as possible */
1047 ++ if (free_length < idle_spawn_rate) {
1048 ++ free_slots[free_length] = i;
1049 ++ ++free_length;
1050 ++ }
1051 ++ }
1052 ++ else {
1053 ++ /* We consider a starting server as idle because we started it
1054 ++ * at least a cycle ago, and if it still hasn't finished starting
1055 ++ * then we're just going to swamp things worse by forking more.
1056 ++ * So we hopefully won't need to fork more if we count it.
1057 ++ * This depends on the ordering of SERVER_READY and SERVER_STARTING.
1058 ++ */
1059 ++ if (status <= SERVER_READY) {
1060 ++ ++ idle_count;
1061 ++ /* always kill the highest numbered child if we have to...
1062 ++ * no really well thought out reason ... other than observing
1063 ++ * the server behaviour under linux where lower numbered children
1064 ++ * tend to service more hits (and hence are more likely to have
1065 ++ * their data in cpu caches).
1066 ++ */
1067 ++ to_kill = i;
1068 ++ }
1069 ++
1070 ++ ++total_non_dead;
1071 ++ last_non_dead = i;
1072 ++ }
1073 ++ }
1074 ++ ap_max_daemons_limit = last_non_dead + 1;
1075 ++ if (idle_count > ap_daemons_max_free) {
1076 ++ /* kill off one child... we use the pod because that'll cause it to
1077 ++ * shut down gracefully, in case it happened to pick up a request
1078 ++ * while we were counting
1079 ++ */
1080 ++ ap_mpm_pod_signal(pod);
1081 ++ idle_spawn_rate = 1;
1082 ++ }
1083 ++ else if (idle_count < ap_daemons_min_free) {
1084 ++ /* terminate the free list */
1085 ++ if (free_length == 0) {
1086 ++ /* only report this condition once */
1087 ++ static int reported = 0;
1088 ++
1089 ++ if (!reported) {
1090 ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
1091 ++ "server reached MaxClients setting, consider"
1092 ++ " raising the MaxClients setting");
1093 ++ reported = 1;
1094 ++ }
1095 ++ idle_spawn_rate = 1;
1096 ++ }
1097 ++ else {
1098 ++ if (idle_spawn_rate >= 8) {
1099 ++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
1100 ++ "server seems busy, (you may need "
1101 ++ "to increase StartServers, or Min/MaxSpareServers), "
1102 ++ "spawning %d children, there are %d idle, and "
1103 ++ "%d total children", idle_spawn_rate,
1104 ++ idle_count, total_non_dead);
1105 ++ }
1106 ++ for (i = 0; i < free_length; ++i) {
1107 ++#ifdef TPF
1108 ++ if (make_child(ap_server_conf, free_slots[i]) == -1) {
1109 ++ if(free_length == 1) {
1110 ++ shutdown_pending = 1;
1111 ++ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, ap_server_conf,
1112 ++ "No active child processes: shutting down");
1113 ++ }
1114 ++ }
1115 ++#else
1116 ++ make_child(ap_server_conf, free_slots[i]);
1117 ++#endif /* TPF */
1118 ++ }
1119 ++ /* the next time around we want to spawn twice as many if this
1120 ++ * wasn't good enough, but not if we've just done a graceful
1121 ++ */
1122 ++ if (hold_off_on_exponential_spawning) {
1123 ++ --hold_off_on_exponential_spawning;
1124 ++ }
1125 ++ else if (idle_spawn_rate < MAX_SPAWN_RATE) {
1126 ++ idle_spawn_rate *= 2;
1127 ++ }
1128 ++ }
1129 ++ }
1130 ++ else {
1131 ++ idle_spawn_rate = 1;
1132 ++ }
1133 ++}
1134 ++
1135 ++/*****************************************************************
1136 ++ * Executive routines.
1137 ++ */
1138 ++
1139 ++int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
1140 ++{
1141 ++ int index;
1142 ++ int remaining_children_to_start;
1143 ++ apr_status_t rv;
1144 ++
1145 ++ ap_log_pid(pconf, ap_pid_fname);
1146 ++
1147 ++ first_server_limit = server_limit;
1148 ++ if (changed_limit_at_restart) {
1149 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
1150 ++ "WARNING: Attempt to change ServerLimit "
1151 ++ "ignored during restart");
1152 ++ changed_limit_at_restart = 0;
1153 ++ }
1154 ++
1155 ++ /* Initialize cross-process accept lock */
1156 ++ ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT,
1157 ++ ap_server_root_relative(_pconf, ap_lock_fname),
1158 ++ ap_my_pid);
1159 ++
1160 ++ rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname,
1161 ++ ap_accept_lock_mech, _pconf);
1162 ++ if (rv != APR_SUCCESS) {
1163 ++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1164 ++ "Couldn't create accept lock (%s) (%d)",
1165 ++ ap_lock_fname, ap_accept_lock_mech);
1166 ++ mpm_state = AP_MPMQ_STOPPING;
1167 ++ return 1;
1168 ++ }
1169 ++
1170 ++#if APR_USE_SYSVSEM_SERIALIZE
1171 ++ if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||
1172 ++ ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1173 ++#else
1174 ++ if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
1175 ++#endif
1176 ++ rv = unixd_set_proc_mutex_perms(accept_mutex);
1177 ++ if (rv != APR_SUCCESS) {
1178 ++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
1179 ++ "Couldn't set permissions on cross-process lock; "
1180 ++ "check User and Group directives");
1181 ++ mpm_state = AP_MPMQ_STOPPING;
1182 ++ return 1;
1183 ++ }
1184 ++ }
1185 ++
1186 ++ if (!is_graceful) {
1187 ++ if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
1188 ++ mpm_state = AP_MPMQ_STOPPING;
1189 ++ return 1;
1190 ++ }
1191 ++ /* fix the generation number in the global score; we just got a new,
1192 ++ * cleared scoreboard
1193 ++ */
1194 ++ ap_scoreboard_image->global->running_generation = ap_my_generation;
1195 ++ }
1196 ++
1197 ++ set_signals();
1198 ++
1199 ++ if (one_process) {
1200 ++ AP_MONCONTROL(1);
1201 ++ make_child(ap_server_conf, 0);
1202 ++ }
1203 ++ else {
1204 ++ if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
1205 ++ ap_daemons_max_free = ap_daemons_min_free + 1;
1206 ++
1207 ++ /* If we're doing a graceful_restart then we're going to see a lot
1208 ++ * of children exiting immediately when we get into the main loop
1209 ++ * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
1210 ++ * rapidly... and for each one that exits we'll start a new one until
1211 ++ * we reach at least daemons_min_free. But we may be permitted to
1212 ++ * start more than that, so we'll just keep track of how many we're
1213 ++ * supposed to start up without the 1 second penalty between each fork.
1214 ++ */
1215 ++ remaining_children_to_start = ap_daemons_to_start;
1216 ++ if (remaining_children_to_start > ap_daemons_limit) {
1217 ++ remaining_children_to_start = ap_daemons_limit;
1218 ++ }
1219 ++ if (!is_graceful) {
1220 ++ startup_children(remaining_children_to_start);
1221 ++ remaining_children_to_start = 0;
1222 ++ }
1223 ++ else {
1224 ++ /* give the system some time to recover before kicking into
1225 ++ * exponential mode
1226 ++ */
1227 ++ hold_off_on_exponential_spawning = 10;
1228 ++ }
1229 ++
1230 ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1231 ++ "%s configured -- resuming normal operations",
1232 ++ ap_get_server_description());
1233 ++ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
1234 ++ "Server built: %s", ap_get_server_built());
1235 ++#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
1236 ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
1237 ++ "AcceptMutex: %s (default: %s)",
1238 ++ apr_proc_mutex_name(accept_mutex),
1239 ++ apr_proc_mutex_defname());
1240 ++#endif
1241 ++ restart_pending = shutdown_pending = 0;
1242 ++
1243 ++ mpm_state = AP_MPMQ_RUNNING;
1244 ++
1245 ++ while (!restart_pending && !shutdown_pending) {
1246 ++ int child_slot;
1247 ++ apr_exit_why_e exitwhy;
1248 ++ int status, processed_status;
1249 ++ /* this is a memory leak, but I'll fix it later. */
1250 ++ apr_proc_t pid;
1251 ++
1252 ++ ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
1253 ++
1254 ++ /* XXX: if it takes longer than 1 second for all our children
1255 ++ * to start up and get into IDLE state then we may spawn an
1256 ++ * extra child
1257 ++ */
1258 ++ if (pid.pid != -1) {
1259 ++ processed_status = ap_process_child_status(&pid, exitwhy, status);
1260 ++ if (processed_status == APEXIT_CHILDFATAL) {
1261 ++ mpm_state = AP_MPMQ_STOPPING;
1262 ++ return 1;
1263 ++ }
1264 ++
1265 ++ /* non-fatal death... note that it's gone in the scoreboard. */
1266 ++ child_slot = find_child_by_pid(&pid);
1267 ++ if (child_slot >= 0) {
1268 ++ (void) ap_update_child_status_from_indexes(child_slot, 0, SERVER_DEAD,
1269 ++ (request_rec *) NULL);
1270 ++ if (processed_status == APEXIT_CHILDSICK) {
1271 ++ /* child detected a resource shortage (E[NM]FILE, ENOBUFS, etc)
1272 ++ * cut the fork rate to the minimum
1273 ++ */
1274 ++ idle_spawn_rate = 1;
1275 ++ }
1276 ++ else if (remaining_children_to_start
1277 ++ && child_slot < ap_daemons_limit) {
1278 ++ /* we're still doing a 1-for-1 replacement of dead
1279 ++ * children with new children
1280 ++ */
1281 ++ make_child(ap_server_conf, child_slot);
1282 ++ --remaining_children_to_start;
1283 ++ }
1284 ++#if APR_HAS_OTHER_CHILD
1285 ++ }
1286 ++ else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH, status) == APR_SUCCESS) {
1287 ++ /* handled */
1288 ++#endif
1289 ++ }
1290 ++ else if (is_graceful) {
1291 ++ /* Great, we've probably just lost a slot in the
1292 ++ * scoreboard. Somehow we don't know about this
1293 ++ * child.
1294 ++ */
1295 ++ ap_log_error(APLOG_MARK, APLOG_WARNING,
1296 ++ 0, ap_server_conf,
1297 ++ "long lost child came home! (pid %ld)", (long)pid.pid);
1298 ++ }
1299 ++ /* Don't perform idle maintenance when a child dies,
1300 ++ * only do it when there's a timeout. Remember only a
1301 ++ * finite number of children can die, and it's pretty
1302 ++ * pathological for a lot to die suddenly.
1303 ++ */
1304 ++ continue;
1305 ++ }
1306 ++ else if (remaining_children_to_start) {
1307 ++ /* we hit a 1 second timeout in which none of the previous
1308 ++ * generation of children needed to be reaped... so assume
1309 ++ * they're all done, and pick up the slack if any is left.
1310 ++ */
1311 ++ startup_children(remaining_children_to_start);
1312 ++ remaining_children_to_start = 0;
1313 ++ /* In any event we really shouldn't do the code below because
1314 ++ * few of the servers we just started are in the IDLE state
1315 ++ * yet, so we'd mistakenly create an extra server.
1316 ++ */
1317 ++ continue;
1318 ++ }
1319 ++
1320 ++ perform_idle_server_maintenance(pconf);
1321 ++#ifdef TPF
1322 ++ shutdown_pending = os_check_server(tpf_server_name);
1323 ++ ap_check_signals();
1324 ++ sleep(1);
1325 ++#endif /*TPF */
1326 ++ }
1327 ++ } /* one_process */
1328 ++
1329 ++ mpm_state = AP_MPMQ_STOPPING;
1330 ++
1331 ++ if (shutdown_pending && !is_graceful) {
1332 ++ /* Time to shut down:
1333 ++ * Kill child processes, tell them to call child_exit, etc...
1334 ++ */
1335 ++ if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
1336 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
1337 ++ }
1338 ++ ap_reclaim_child_processes(1); /* Start with SIGTERM */
1339 ++
1340 ++ /* cleanup pid file on normal shutdown */
1341 ++ {
1342 ++ const char *pidfile = NULL;
1343 ++ pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1344 ++ if ( pidfile != NULL && unlink(pidfile) == 0)
1345 ++ ap_log_error(APLOG_MARK, APLOG_INFO,
1346 ++ 0, ap_server_conf,
1347 ++ "removed PID file %s (pid=%ld)",
1348 ++ pidfile, (long)getpid());
1349 ++ }
1350 ++
1351 ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1352 ++ "caught SIGTERM, shutting down");
1353 ++
1354 ++ return 1;
1355 ++ } else if (shutdown_pending) {
1356 ++ /* Time to perform a graceful shut down:
1357 ++ * Reap the inactive children, and ask the active ones
1358 ++ * to close their listeners, then wait until they are
1359 ++ * all done to exit.
1360 ++ */
1361 ++ int active_children;
1362 ++ apr_time_t cutoff = 0;
1363 ++
1364 ++ /* Stop listening */
1365 ++ ap_close_listeners();
1366 ++
1367 ++ /* kill off the idle ones */
1368 ++ ap_mpm_pod_killpg(pod, ap_max_daemons_limit);
1369 ++
1370 ++ /* Send SIGUSR1 to the active children */
1371 ++ active_children = 0;
1372 ++ for (index = 0; index < ap_daemons_limit; ++index) {
1373 ++ if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
1374 ++ /* Ask each child to close its listeners. */
1375 ++ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
1376 ++ active_children++;
1377 ++ }
1378 ++ }
1379 ++
1380 ++ /* Allow each child which actually finished to exit */
1381 ++ ap_relieve_child_processes();
1382 ++
1383 ++ /* cleanup pid file */
1384 ++ {
1385 ++ const char *pidfile = NULL;
1386 ++ pidfile = ap_server_root_relative (pconf, ap_pid_fname);
1387 ++ if ( pidfile != NULL && unlink(pidfile) == 0)
1388 ++ ap_log_error(APLOG_MARK, APLOG_INFO,
1389 ++ 0, ap_server_conf,
1390 ++ "removed PID file %s (pid=%ld)",
1391 ++ pidfile, (long)getpid());
1392 ++ }
1393 ++
1394 ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1395 ++ "caught " AP_SIG_GRACEFUL_STOP_STRING ", shutting down gracefully");
1396 ++
1397 ++ if (ap_graceful_shutdown_timeout) {
1398 ++ cutoff = apr_time_now() +
1399 ++ apr_time_from_sec(ap_graceful_shutdown_timeout);
1400 ++ }
1401 ++
1402 ++ /* Don't really exit until each child has finished */
1403 ++ shutdown_pending = 0;
1404 ++ do {
1405 ++ /* Pause for a second */
1406 ++ sleep(1);
1407 ++
1408 ++ /* Relieve any children which have now exited */
1409 ++ ap_relieve_child_processes();
1410 ++
1411 ++ active_children = 0;
1412 ++ for (index = 0; index < ap_daemons_limit; ++index) {
1413 ++ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
1414 ++ active_children = 1;
1415 ++ /* Having just one child is enough to stay around */
1416 ++ break;
1417 ++ }
1418 ++ }
1419 ++ } while (!shutdown_pending && active_children &&
1420 ++ (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
1421 ++
1422 ++ /* We might be here because we received SIGTERM, either
1423 ++ * way, try and make sure that all of our processes are
1424 ++ * really dead.
1425 ++ */
1426 ++ unixd_killpg(getpgrp(), SIGTERM);
1427 ++
1428 ++ return 1;
1429 ++ }
1430 ++
1431 ++ /* we've been told to restart */
1432 ++ apr_signal(SIGHUP, SIG_IGN);
1433 ++ apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
1434 ++ if (one_process) {
1435 ++ /* not worth thinking about */
1436 ++ return 1;
1437 ++ }
1438 ++
1439 ++ /* advance to the next generation */
1440 ++ /* XXX: we really need to make sure this new generation number isn't in
1441 ++ * use by any of the children.
1442 ++ */
1443 ++ ++ap_my_generation;
1444 ++ ap_scoreboard_image->global->running_generation = ap_my_generation;
1445 ++
1446 ++ if (is_graceful) {
1447 ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1448 ++ "Graceful restart requested, doing restart");
1449 ++
1450 ++ /* kill off the idle ones */
1451 ++ ap_mpm_pod_killpg(pod, ap_max_daemons_limit);
1452 ++
1453 ++ /* This is mostly for debugging... so that we know what is still
1454 ++ * gracefully dealing with existing request. This will break
1455 ++ * in a very nasty way if we ever have the scoreboard totally
1456 ++ * file-based (no shared memory)
1457 ++ */
1458 ++ for (index = 0; index < ap_daemons_limit; ++index) {
1459 ++ if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
1460 ++ ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL;
1461 ++ /* Ask each child to close its listeners.
1462 ++ *
1463 ++ * NOTE: we use the scoreboard, because if we send SIGUSR1
1464 ++ * to every process in the group, this may include CGI's,
1465 ++ * piped loggers, etc. They almost certainly won't handle
1466 ++ * it gracefully.
1467 ++ */
1468 ++ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
1469 ++ }
1470 ++ }
1471 ++ }
1472 ++ else {
1473 ++ /* Kill 'em off */
1474 ++ if (unixd_killpg(getpgrp(), SIGHUP) < 0) {
1475 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGHUP");
1476 ++ }
1477 ++ ap_reclaim_child_processes(0); /* Not when just starting up */
1478 ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
1479 ++ "SIGHUP received. Attempting to restart");
1480 ++ }
1481 ++
1482 ++ return 0;
1483 ++}
1484 ++
1485 ++/* This really should be a post_config hook, but the error log is already
1486 ++ * redirected by that point, so we need to do this in the open_logs phase.
1487 ++ */
1488 ++static int itk_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1489 ++{
1490 ++ apr_status_t rv;
1491 ++
1492 ++ pconf = p;
1493 ++ ap_server_conf = s;
1494 ++
1495 ++ if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
1496 ++ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0,
1497 ++ NULL, "no listening sockets available, shutting down");
1498 ++ return DONE;
1499 ++ }
1500 ++
1501 ++ if ((rv = ap_mpm_pod_open(pconf, &pod))) {
1502 ++ ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_STARTUP, rv, NULL,
1503 ++ "Could not open pipe-of-death.");
1504 ++ return DONE;
1505 ++ }
1506 ++ return OK;
1507 ++}
1508 ++
1509 ++static int itk_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
1510 ++{
1511 ++ static int restart_num = 0;
1512 ++ int no_detach, debug, foreground;
1513 ++ apr_status_t rv;
1514 ++
1515 ++ mpm_state = AP_MPMQ_STARTING;
1516 ++
1517 ++ debug = ap_exists_config_define("DEBUG");
1518 ++
1519 ++ if (debug) {
1520 ++ foreground = one_process = 1;
1521 ++ no_detach = 0;
1522 ++ }
1523 ++ else
1524 ++ {
1525 ++ no_detach = ap_exists_config_define("NO_DETACH");
1526 ++ one_process = ap_exists_config_define("ONE_PROCESS");
1527 ++ foreground = ap_exists_config_define("FOREGROUND");
1528 ++ }
1529 ++
1530 ++ /* sigh, want this only the second time around */
1531 ++ if (restart_num++ == 1) {
1532 ++ is_graceful = 0;
1533 ++
1534 ++ if (!one_process && !foreground) {
1535 ++ rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
1536 ++ : APR_PROC_DETACH_DAEMONIZE);
1537 ++ if (rv != APR_SUCCESS) {
1538 ++ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
1539 ++ "apr_proc_detach failed");
1540 ++ return HTTP_INTERNAL_SERVER_ERROR;
1541 ++ }
1542 ++ }
1543 ++
1544 ++ parent_pid = ap_my_pid = getpid();
1545 ++ }
1546 ++
1547 ++ unixd_pre_config(ptemp);
1548 ++ ap_listen_pre_config();
1549 ++ ap_daemons_to_start = DEFAULT_START_DAEMON;
1550 ++ ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
1551 ++ ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
1552 ++ ap_daemons_limit = server_limit;
1553 ++ ap_pid_fname = DEFAULT_PIDLOG;
1554 ++ ap_lock_fname = DEFAULT_LOCKFILE;
1555 ++ ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
1556 ++ ap_extended_status = 0;
1557 ++#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
1558 ++ ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
1559 ++#endif
1560 ++
1561 ++ apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
1562 ++
1563 ++ return OK;
1564 ++}
1565 ++
1566 ++static int itk_post_perdir_config(request_rec *r)
1567 ++{
1568 ++ uid_t wanted_uid;
1569 ++ gid_t wanted_gid;
1570 ++ const char *wanted_username;
1571 ++ int err = 0;
1572 ++
1573 ++ itk_server_conf *sconf =
1574 ++ (itk_server_conf *) ap_get_module_config(r->server->module_config, &mpm_itk_module);
1575 ++
1576 ++ /* Enforce MaxClientsVhost. */
1577 ++ if (sconf->max_clients_vhost > 0) {
1578 ++ int i, num_other_servers = 0;
1579 ++ for (i = 0; i < ap_daemons_limit; ++i) {
1580 ++ worker_score *ws = &ap_scoreboard_image->servers[i][0];
1581 ++ if (ws->status >= SERVER_BUSY_READ && strncmp(ws->vhost, r->server->server_hostname, 31) == 0)
1582 ++ ++num_other_servers;
1583 ++ }
1584 ++
1585 ++ if (num_other_servers > sconf->max_clients_vhost) {
1586 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \
1587 ++ "MaxClientsVhost reached for %s, refusing client.",
1588 ++ r->server->server_hostname);
1589 ++ return HTTP_SERVICE_UNAVAILABLE;
1590 ++ }
1591 ++ }
1592 ++
1593 ++ itk_per_dir_conf *dconf =
1594 ++ (itk_per_dir_conf *) ap_get_module_config(r->per_dir_config, &mpm_itk_module);
1595 ++
1596 ++ strncpy(ap_scoreboard_image->servers[my_child_num][0].vhost, r->server->server_hostname, 31);
1597 ++ ap_scoreboard_image->servers[my_child_num][0].vhost[31] = 0;
1598 ++
1599 ++ if (dconf->nice_value != UNSET_NICE_VALUE &&
1600 ++ setpriority(PRIO_PROCESS, 0, dconf->nice_value)) {
1601 ++ _DBG("setpriority(): %s", strerror(errno));
1602 ++ err = 1;
1603 ++ }
1604 ++
1605 ++ wanted_uid = dconf->uid;
1606 ++ wanted_gid = dconf->gid;
1607 ++ wanted_username = dconf->username;
1608 ++
1609 ++ if (wanted_uid == -1 || wanted_gid == -1) {
1610 ++ wanted_uid = unixd_config.user_id;
1611 ++ wanted_gid = unixd_config.group_id;
1612 ++ wanted_username = unixd_config.user_name;
1613 ++ }
1614 ++
1615 ++ if (!err && wanted_uid != -1 && wanted_gid != -1 && (getuid() != wanted_uid || getgid() != wanted_gid)) {
1616 ++ if (setgid(wanted_gid)) {
1617 ++ _DBG("setgid(%d): %s", wanted_gid, strerror(errno));
1618 ++ err = 1;
1619 ++ } else if (initgroups(wanted_username, wanted_gid)) {
1620 ++ _DBG("initgroups(%s, %d): %s", wanted_username, wanted_gid, strerror(errno));
1621 ++ err = 1;
1622 ++ } else if (setuid(wanted_uid)) {
1623 ++ _DBG("setuid(%d): %s", wanted_uid, strerror(errno));
1624 ++ err = 1;
1625 ++ }
1626 ++ }
1627 ++
1628 ++ /*
1629 ++ * Most likely a case of switching uid/gid within a persistent
1630 ++ * connection; the RFCs allow us to just close the connection
1631 ++ * at anytime, so we excercise our right. :-)
1632 ++ */
1633 ++ if (err) {
1634 ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \
1635 ++ "Couldn't set uid/gid/priority, closing connection.");
1636 ++ ap_lingering_close(r->connection);
1637 ++ exit(0);
1638 ++ }
1639 ++ return OK;
1640 ++}
1641 ++
1642 ++static void itk_hooks(apr_pool_t *p)
1643 ++{
1644 ++ /* The itk open_logs phase must run before the core's, or stderr
1645 ++ * will be redirected to a file, and the messages won't print to the
1646 ++ * console.
1647 ++ */
1648 ++ static const char *const aszSucc[] = {"core.c", NULL};
1649 ++
1650 ++#ifdef AUX3
1651 ++ (void) set42sig();
1652 ++#endif
1653 ++
1654 ++ ap_hook_open_logs(itk_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
1655 ++ /* we need to set the MPM state before other pre-config hooks use MPM query
1656 ++ * to retrieve it, so register as REALLY_FIRST
1657 ++ */
1658 ++ ap_hook_pre_config(itk_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
1659 ++
1660 ++ /* set the uid as fast as possible, but not before merging per-dit config */
1661 ++ ap_hook_header_parser(itk_post_perdir_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
1662 ++}
1663 ++
1664 ++static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
1665 ++{
1666 ++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1667 ++ if (err != NULL) {
1668 ++ return err;
1669 ++ }
1670 ++
1671 ++ ap_daemons_to_start = atoi(arg);
1672 ++ return NULL;
1673 ++}
1674 ++
1675 ++static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
1676 ++{
1677 ++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1678 ++ if (err != NULL) {
1679 ++ return err;
1680 ++ }
1681 ++
1682 ++ ap_daemons_min_free = atoi(arg);
1683 ++ if (ap_daemons_min_free <= 0) {
1684 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1685 ++ "WARNING: detected MinSpareServers set to non-positive.");
1686 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1687 ++ "Resetting to 1 to avoid almost certain Apache failure.");
1688 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1689 ++ "Please read the documentation.");
1690 ++ ap_daemons_min_free = 1;
1691 ++ }
1692 ++
1693 ++ return NULL;
1694 ++}
1695 ++
1696 ++static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
1697 ++{
1698 ++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1699 ++ if (err != NULL) {
1700 ++ return err;
1701 ++ }
1702 ++
1703 ++ ap_daemons_max_free = atoi(arg);
1704 ++ return NULL;
1705 ++}
1706 ++
1707 ++static const char *set_max_clients (cmd_parms *cmd, void *dummy, const char *arg)
1708 ++{
1709 ++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1710 ++ if (err != NULL) {
1711 ++ return err;
1712 ++ }
1713 ++
1714 ++ ap_daemons_limit = atoi(arg);
1715 ++ if (ap_daemons_limit > server_limit) {
1716 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1717 ++ "WARNING: MaxClients of %d exceeds ServerLimit value "
1718 ++ "of %d servers,", ap_daemons_limit, server_limit);
1719 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1720 ++ " lowering MaxClients to %d. To increase, please "
1721 ++ "see the ServerLimit", server_limit);
1722 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1723 ++ " directive.");
1724 ++ ap_daemons_limit = server_limit;
1725 ++ }
1726 ++ else if (ap_daemons_limit < 1) {
1727 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1728 ++ "WARNING: Require MaxClients > 0, setting to 1");
1729 ++ ap_daemons_limit = 1;
1730 ++ }
1731 ++ return NULL;
1732 ++}
1733 ++
1734 ++static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
1735 ++{
1736 ++ int tmp_server_limit;
1737 ++
1738 ++ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
1739 ++ if (err != NULL) {
1740 ++ return err;
1741 ++ }
1742 ++
1743 ++ tmp_server_limit = atoi(arg);
1744 ++ /* you cannot change ServerLimit across a restart; ignore
1745 ++ * any such attempts
1746 ++ */
1747 ++ if (first_server_limit &&
1748 ++ tmp_server_limit != server_limit) {
1749 ++ /* how do we log a message? the error log is a bit bucket at this
1750 ++ * point; we'll just have to set a flag so that ap_mpm_run()
1751 ++ * logs a warning later
1752 ++ */
1753 ++ changed_limit_at_restart = 1;
1754 ++ return NULL;
1755 ++ }
1756 ++ server_limit = tmp_server_limit;
1757 ++
1758 ++ if (server_limit > MAX_SERVER_LIMIT) {
1759 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1760 ++ "WARNING: ServerLimit of %d exceeds compile time limit "
1761 ++ "of %d servers,", server_limit, MAX_SERVER_LIMIT);
1762 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1763 ++ " lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
1764 ++ server_limit = MAX_SERVER_LIMIT;
1765 ++ }
1766 ++ else if (server_limit < 1) {
1767 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1768 ++ "WARNING: Require ServerLimit > 0, setting to 1");
1769 ++ server_limit = 1;
1770 ++ }
1771 ++ return NULL;
1772 ++}
1773 ++
1774 ++static const char *assign_user_id (cmd_parms *cmd, void *ptr, const char *user_name, const char *group_name)
1775 ++{
1776 ++ itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr;
1777 ++ dconf->username = apr_pstrdup(cmd->pool, user_name);
1778 ++ dconf->uid = ap_uname2id(user_name);
1779 ++ dconf->gid = ap_gname2id(group_name);
1780 ++ return NULL;
1781 ++}
1782 ++
1783 ++static const char *set_max_clients_vhost (cmd_parms *cmd, void *dummy, const char *arg)
1784 ++{
1785 ++ itk_server_conf *sconf =
1786 ++ (itk_server_conf *) ap_get_module_config(cmd->server->module_config, &mpm_itk_module);
1787 ++ sconf->max_clients_vhost = atoi(arg);
1788 ++ return NULL;
1789 ++}
1790 ++
1791 ++static const char *set_nice_value (cmd_parms *cmd, void *ptr, const char *arg)
1792 ++{
1793 ++ itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr;
1794 ++ int nice_value = atoi(arg);
1795 ++
1796 ++ if (nice_value < -20) {
1797 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1798 ++ "WARNING: NiceValue of %d is below -20, increasing NiceValue to -20.",
1799 ++ nice_value);
1800 ++ nice_value = -20;
1801 ++ }
1802 ++ else if (nice_value > 19) {
1803 ++ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1804 ++ "WARNING: NiceValue of %d is above 19, lowering NiceValue to 19.",
1805 ++ nice_value);
1806 ++ nice_value = 19;
1807 ++ }
1808 ++ dconf->nice_value = nice_value;
1809 ++ return NULL;
1810 ++}
1811 ++
1812 ++static const command_rec itk_cmds[] = {
1813 ++UNIX_DAEMON_COMMANDS,
1814 ++LISTEN_COMMANDS,
1815 ++AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
1816 ++ "Number of child processes launched at server startup"),
1817 ++AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
1818 ++ "Minimum number of idle children, to handle request spikes"),
1819 ++AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF,
1820 ++ "Maximum number of idle children"),
1821 ++AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
1822 ++ "Maximum number of children alive at the same time"),
1823 ++AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
1824 ++ "Maximum value of MaxClients for this run of Apache"),
1825 ++AP_INIT_TAKE2("AssignUserID", assign_user_id, NULL, RSRC_CONF|ACCESS_CONF,
1826 ++ "Tie a virtual host to a specific child process."),
1827 ++AP_INIT_TAKE1("MaxClientsVHost", set_max_clients_vhost, NULL, RSRC_CONF,
1828 ++ "Maximum number of children alive at the same time for this virtual host."),
1829 ++AP_INIT_TAKE1("NiceValue", set_nice_value, NULL, RSRC_CONF|ACCESS_CONF,
1830 ++ "Set nice value for the given vhost, from -20 (highest priority) to 19 (lowest priority)."),
1831 ++AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
1832 ++{ NULL }
1833 ++};
1834 ++
1835 ++/* == allocate a private per-dir config structure == */
1836 ++static void *itk_create_dir_config(apr_pool_t *p, char *dummy)
1837 ++{
1838 ++ itk_per_dir_conf *c = (itk_per_dir_conf *)
1839 ++ apr_pcalloc(p, sizeof(itk_per_dir_conf));
1840 ++ c->uid = c->gid = -1;
1841 ++ c->nice_value = UNSET_NICE_VALUE;
1842 ++ return c;
1843 ++}
1844 ++
1845 ++/* == merge the parent per-dir config structure into ours == */
1846 ++static void *itk_merge_dir_config(apr_pool_t *p, void *parent_ptr, void *child_ptr)
1847 ++{
1848 ++ itk_per_dir_conf *c = (itk_per_dir_conf *)
1849 ++ itk_create_dir_config(p, NULL);
1850 ++ itk_per_dir_conf *parent = (itk_per_dir_conf *) parent_ptr;
1851 ++ itk_per_dir_conf *child = (itk_per_dir_conf *) child_ptr;
1852 ++
1853 ++ if (child->username != NULL) {
1854 ++ c->username = child->username;
1855 ++ c->uid = child->uid;
1856 ++ c->gid = child->gid;
1857 ++ } else {
1858 ++ c->username = parent->username;
1859 ++ c->uid = parent->uid;
1860 ++ c->gid = parent->gid;
1861 ++ }
1862 ++ if (child->nice_value != UNSET_NICE_VALUE) {
1863 ++ c->nice_value = child->nice_value;
1864 ++ } else {
1865 ++ c->nice_value = parent->nice_value;
1866 ++ }
1867 ++ return c;
1868 ++}
1869 ++
1870 ++/* == allocate a private server config structure == */
1871 ++static void *itk_create_server_config(apr_pool_t *p, server_rec *s)
1872 ++{
1873 ++ itk_server_conf *c = (itk_server_conf *)
1874 ++ apr_pcalloc(p, sizeof(itk_server_conf));
1875 ++ c->max_clients_vhost = -1;
1876 ++ return c;
1877 ++}
1878 ++
1879 ++module AP_MODULE_DECLARE_DATA mpm_itk_module = {
1880 ++ MPM20_MODULE_STUFF,
1881 ++ ap_mpm_rewrite_args, /* hook to run before apache parses args */
1882 ++ itk_create_dir_config, /* create per-directory config structure */
1883 ++ itk_merge_dir_config, /* merge per-directory config structures */
1884 ++ itk_create_server_config, /* create per-server config structure */
1885 ++ NULL, /* merge per-server config structures */
1886 ++ itk_cmds, /* command apr_table_t */
1887 ++ itk_hooks, /* register hooks */
1888 ++};
1889 +unchanged:
1890 +--- httpd-2.2.17/server/mpm/experimental/itk/mpm.h
1891 ++++ httpd-2.2.17/server/mpm/experimental/itk/mpm.h
1892 +@@ -0,0 +1,68 @@
1893 ++/* Licensed to the Apache Software Foundation (ASF) under one or more
1894 ++ * contributor license agreements. See the NOTICE file distributed with
1895 ++ * this work for additional information regarding copyright ownership.
1896 ++ * The ASF licenses this file to You under the Apache License, Version 2.0
1897 ++ * (the "License"); you may not use this file except in compliance with
1898 ++ * the License. You may obtain a copy of the License at
1899 ++ *
1900 ++ * http://www.apache.org/licenses/LICENSE-2.0
1901 ++ *
1902 ++ * Unless required by applicable law or agreed to in writing, software
1903 ++ * distributed under the License is distributed on an "AS IS" BASIS,
1904 ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1905 ++ * See the License for the specific language governing permissions and
1906 ++ * limitations under the License.
1907 ++ *
1908 ++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
1909 ++ * Licensed under the same terms as the rest of Apache.
1910 ++ *
1911 ++ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
1912 ++ * Licensed under the same terms as the rest of Apache.
1913 ++ */
1914 ++
1915 ++/**
1916 ++ * @file itk/mpm.h
1917 ++ * @brief ITK MPM (setuid per-vhost, no threads)
1918 ++ *
1919 ++ * @defgroup APACHE_MPM_ITK Apache ITK
1920 ++ * @ingroup APACHE_MPM APACHE_OS_UNIX
1921 ++ * @{
1922 ++ */
1923 ++
1924 ++#include "httpd.h"
1925 ++#include "mpm_default.h"
1926 ++#include "scoreboard.h"
1927 ++#include "unixd.h"
1928 ++
1929 ++#ifndef APACHE_MPM_ITK_H
1930 ++#define APACHE_MPM_ITK_H
1931 ++
1932 ++#define ITK_MPM
1933 ++
1934 ++#define MPM_NAME "ITK"
1935 ++
1936 ++#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
1937 ++#define AP_MPM_WANT_WAIT_OR_TIMEOUT
1938 ++#define AP_MPM_WANT_PROCESS_CHILD_STATUS
1939 ++#define AP_MPM_WANT_SET_PIDFILE
1940 ++#define AP_MPM_WANT_SET_SCOREBOARD
1941 ++#define AP_MPM_WANT_SET_LOCKFILE
1942 ++#define AP_MPM_WANT_SET_MAX_REQUESTS
1943 ++#define AP_MPM_WANT_SET_COREDUMPDIR
1944 ++#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
1945 ++#define AP_MPM_WANT_SIGNAL_SERVER
1946 ++#define AP_MPM_WANT_SET_MAX_MEM_FREE
1947 ++#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER
1948 ++#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN
1949 ++#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
1950 ++
1951 ++#define AP_MPM_USES_POD 1
1952 ++#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
1953 ++#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
1954 ++#define MPM_ACCEPT_FUNC unixd_accept
1955 ++
1956 ++extern int ap_threads_per_child;
1957 ++extern int ap_max_daemons_limit;
1958 ++extern server_rec *ap_server_conf;
1959 ++#endif /* APACHE_MPM_ITK_H */
1960 ++/** @} */
1961 +unchanged:
1962 +--- httpd-2.2.17/server/mpm/experimental/itk/mpm_default.h
1963 ++++ httpd-2.2.17/server/mpm/experimental/itk/mpm_default.h
1964 +@@ -0,0 +1,80 @@
1965 ++/* Licensed to the Apache Software Foundation (ASF) under one or more
1966 ++ * contributor license agreements. See the NOTICE file distributed with
1967 ++ * this work for additional information regarding copyright ownership.
1968 ++ * The ASF licenses this file to You under the Apache License, Version 2.0
1969 ++ * (the "License"); you may not use this file except in compliance with
1970 ++ * the License. You may obtain a copy of the License at
1971 ++ *
1972 ++ * http://www.apache.org/licenses/LICENSE-2.0
1973 ++ *
1974 ++ * Unless required by applicable law or agreed to in writing, software
1975 ++ * distributed under the License is distributed on an "AS IS" BASIS,
1976 ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1977 ++ * See the License for the specific language governing permissions and
1978 ++ * limitations under the License.
1979 ++ *
1980 ++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
1981 ++ * Licensed under the same terms as the rest of Apache.
1982 ++ *
1983 ++ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
1984 ++ * Licensed under the same terms as the rest of Apache.
1985 ++ */
1986 ++
1987 ++/**
1988 ++ * @file itk/mpm_default.h
1989 ++ * @brief ITK MPM defaults
1990 ++ *
1991 ++ * @addtogroup APACHE_MPM_ITK
1992 ++ * @{
1993 ++ */
1994 ++
1995 ++#ifndef APACHE_MPM_DEFAULT_H
1996 ++#define APACHE_MPM_DEFAULT_H
1997 ++
1998 ++/* Number of servers to spawn off by default --- also, if fewer than
1999 ++ * this free when the caretaker checks, it will spawn more.
2000 ++ */
2001 ++#ifndef DEFAULT_START_DAEMON
2002 ++#define DEFAULT_START_DAEMON 5
2003 ++#endif
2004 ++
2005 ++/* Maximum number of *free* server processes --- more than this, and
2006 ++ * they will die off.
2007 ++ */
2008 ++
2009 ++#ifndef DEFAULT_MAX_FREE_DAEMON
2010 ++#define DEFAULT_MAX_FREE_DAEMON 10
2011 ++#endif
2012 ++
2013 ++/* Minimum --- fewer than this, and more will be created */
2014 ++
2015 ++#ifndef DEFAULT_MIN_FREE_DAEMON
2016 ++#define DEFAULT_MIN_FREE_DAEMON 5
2017 ++#endif
2018 ++
2019 ++/* File used for accept locking, when we use a file */
2020 ++#ifndef DEFAULT_LOCKFILE
2021 ++#define DEFAULT_LOCKFILE DEFAULT_REL_RUNTIMEDIR "/accept.lock"
2022 ++#endif
2023 ++
2024 ++/* Where the main/parent process's pid is logged */
2025 ++#ifndef DEFAULT_PIDLOG
2026 ++#define DEFAULT_PIDLOG DEFAULT_REL_RUNTIMEDIR "/httpd.pid"
2027 ++#endif
2028 ++
2029 ++/*
2030 ++ * Interval, in microseconds, between scoreboard maintenance.
2031 ++ */
2032 ++#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
2033 ++#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
2034 ++#endif
2035 ++
2036 ++/* Number of requests to try to handle in a single process. If <= 0,
2037 ++ * the children don't die off.
2038 ++ */
2039 ++#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
2040 ++#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
2041 ++#endif
2042 ++
2043 ++#endif /* AP_MPM_DEFAULT_H */
2044 ++/** @} */
2045 +unchanged:
2046 +--- httpd-2.2.17/server/mpm/config.m4
2047 ++++ httpd-2.2.17/server/mpm/config.m4
2048 +@@ -1,7 +1,7 @@
2049 + AC_MSG_CHECKING(which MPM to use)
2050 + AC_ARG_WITH(mpm,
2051 + APACHE_HELP_STRING(--with-mpm=MPM,Choose the process model for Apache to use.
2052 +- MPM={beos|event|worker|prefork|mpmt_os2|winnt|peruser}),[
2053 ++ MPM={beos|event|worker|prefork|mpmt_os2|winnt|peruser|itk}),[
2054 + APACHE_MPM=$withval
2055 + ],[
2056 + if test "x$APACHE_MPM" = "x"; then
2057 +@@ -23,7 +23,7 @@
2058 +
2059 + ap_mpm_is_experimental ()
2060 + {
2061 +- if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "peruser" ; then
2062 ++ if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "peruser" -o "$apache_cv_mpm" = "itk" ; then
2063 + return 0
2064 + else
2065 + return 1
2066 +@@ -66,6 +66,11 @@
2067 + else
2068 + MPM_SUBDIR_NAME=$MPM_NAME
2069 + fi
2070 ++
2071 ++if test "$apache_cv_mpm" = "itk" ; then
2072 ++ AC_CHECK_LIB(cap, cap_init)
2073 ++fi
2074 ++
2075 + MPM_DIR=server/mpm/$MPM_SUBDIR_NAME
2076 + MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la
2077 +
2078 +unchanged:
2079 +--- httpd-2.2.17/include/http_request.h
2080 ++++ httpd-2.2.17/include/http_request.h
2081 +@@ -12,6 +12,12 @@
2082 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2083 + * See the License for the specific language governing permissions and
2084 + * limitations under the License.
2085 ++ *
2086 ++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
2087 ++ * Licensed under the same terms as the rest of Apache.
2088 ++ *
2089 ++ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
2090 ++ * Licensed under the same terms as the rest of Apache.
2091 + */
2092 +
2093 + /**
2094 +@@ -350,6 +356,15 @@
2095 + */
2096 + AP_DECLARE_HOOK(void,insert_filter,(request_rec *r))
2097 +
2098 ++/**
2099 ++ * This hook allows modules to affect the request immediately after the
2100 ++ * per-directory configuration for the request has been generated. This allows
2101 ++ * modules to make decisions based upon the current directory configuration
2102 ++ * @param r The current request
2103 ++ * @return OK or DECLINED
2104 ++ */
2105 ++AP_DECLARE_HOOK(int,post_perdir_config,(request_rec *r))
2106 ++
2107 + AP_DECLARE(int) ap_location_walk(request_rec *r);
2108 + AP_DECLARE(int) ap_directory_walk(request_rec *r);
2109 + AP_DECLARE(int) ap_file_walk(request_rec *r);
2110 +unchanged:
2111 +--- httpd-2.2.17/server/request.c
2112 ++++ httpd-2.2.17/server/request.c
2113 +@@ -12,6 +12,12 @@
2114 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2115 + * See the License for the specific language governing permissions and
2116 + * limitations under the License.
2117 ++ *
2118 ++ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
2119 ++ * Licensed under the same terms as the rest of Apache.
2120 ++ *
2121 ++ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
2122 ++ * Licensed under the same terms as the rest of Apache.
2123 + */
2124 +
2125 + /*
2126 +@@ -61,6 +67,7 @@
2127 + APR_HOOK_LINK(auth_checker)
2128 + APR_HOOK_LINK(insert_filter)
2129 + APR_HOOK_LINK(create_request)
2130 ++ APR_HOOK_LINK(post_perdir_config)
2131 + )
2132 +
2133 + AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name,
2134 +@@ -80,6 +87,8 @@
2135 + AP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r))
2136 + AP_IMPLEMENT_HOOK_RUN_ALL(int, create_request,
2137 + (request_rec *r), (r), OK, DECLINED)
2138 ++AP_IMPLEMENT_HOOK_RUN_ALL(int,post_perdir_config,
2139 ++ (request_rec *r), (r), OK, DECLINED)
2140 +
2141 +
2142 + static int decl_die(int status, char *phase, request_rec *r)
2143 +@@ -158,6 +167,13 @@
2144 + return access_status;
2145 + }
2146 +
2147 ++ /* First chance to handle the request after per-directory configuration is
2148 ++ * generated
2149 ++ */
2150 ++ if ((access_status = ap_run_post_perdir_config(r))) {
2151 ++ return access_status;
2152 ++ }
2153 ++
2154 + /* Only on the main request! */
2155 + if (r->main == NULL) {
2156 + if ((access_status = ap_run_header_parser(r))) {
2157 +only in patch2:
2158 +unchanged:
2159 +--- httpd-2.2.17.orig/server/config.c
2160 ++++ httpd-2.2.17/server/config.c
2161 +@@ -1840,6 +1840,34 @@ AP_CORE_DECLARE(int) ap_parse_htaccess(a
2162 + else {
2163 + if (!APR_STATUS_IS_ENOENT(status)
2164 + && !APR_STATUS_IS_ENOTDIR(status)) {
2165 ++#ifdef ITK_MPM
2166 ++ /*
2167 ++ * If we are in a persistent connection, we might end up in a state
2168 ++ * where we can no longer read .htaccess files because we have already
2169 ++ * setuid(). This can either be because the previous request was for
2170 ++ * another vhost (basically the same problem as when setuid() fails in
2171 ++ * itk.c), or it can be because a .htaccess file is readable only by
2172 ++ * root.
2173 ++ *
2174 ++ * In any case, we don't want to give out a 403, since the request has
2175 ++ * a very real chance of succeeding on a fresh connection (where
2176 ++ * presumably uid=0). Thus, we give up serving the request on this
2177 ++ * TCP connection, and do a hard close of the socket. As long as we're
2178 ++ * in a persistent connection (and there _should_ not be a way this
2179 ++ * would happen on the first request in a connection, save for subrequests,
2180 ++ * which we special-case), this is allowed, as it is what happens on
2181 ++ * a timeout. The browser will simply open a new connection and try
2182 ++ * again (there's of course a performance hit, though, both due to
2183 ++ * the new connection setup and the fork() of a new server child).
2184 ++ */
2185 ++ if (r->main == NULL && getuid() != 0) {
2186 ++ ap_log_rerror(APLOG_MARK, APLOG_WARNING, status, r,
2187 ++ "Couldn't read %s, closing connection.",
2188 ++ filename);
2189 ++ ap_lingering_close(r->connection);
2190 ++ exit(0);
2191 ++ }
2192 ++#endif
2193 + ap_log_rerror(APLOG_MARK, APLOG_CRIT, status, r,
2194 + "%s pcfg_openfile: unable to check htaccess file, "
2195 + "ensure it is readable",
2196
2197 Deleted: trunk/dist/2.2/patches/21_all_itk_20090114.patch
2198 ===================================================================
2199 --- trunk/dist/2.2/patches/21_all_itk_20090114.patch 2011-02-18 17:28:28 UTC (rev 234)
2200 +++ trunk/dist/2.2/patches/21_all_itk_20090114.patch 2011-09-01 15:33:52 UTC (rev 235)
2201 @@ -1,2036 +0,0 @@
2202 -Index: httpd-2.2.11/server/mpm/experimental/itk/Makefile.in
2203 -===================================================================
2204 ---- /dev/null
2205 -+++ httpd-2.2.11/server/mpm/experimental/itk/Makefile.in
2206 -@@ -0,0 +1,5 @@
2207 -+
2208 -+LTLIBRARY_NAME = libitk.la
2209 -+LTLIBRARY_SOURCES = itk.c
2210 -+
2211 -+include $(top_srcdir)/build/ltlib.mk
2212 -Index: httpd-2.2.11/server/mpm/experimental/itk/config.m4
2213 -===================================================================
2214 ---- /dev/null
2215 -+++ httpd-2.2.11/server/mpm/experimental/itk/config.m4
2216 -@@ -0,0 +1,3 @@
2217 -+if test "$MPM_NAME" = "itk" ; then
2218 -+ APACHE_FAST_OUTPUT(server/mpm/$MPM_SUBDIR_NAME/Makefile)
2219 -+fi
2220 -Index: httpd-2.2.11/server/mpm/experimental/itk/itk.c
2221 -===================================================================
2222 ---- /dev/null
2223 -+++ httpd-2.2.11/server/mpm/experimental/itk/itk.c
2224 -@@ -0,0 +1,1740 @@
2225 -+/* Licensed to the Apache Software Foundation (ASF) under one or more
2226 -+ * contributor license agreements. See the NOTICE file distributed with
2227 -+ * this work for additional information regarding copyright ownership.
2228 -+ * The ASF licenses this file to You under the Apache License, Version 2.0
2229 -+ * (the "License"); you may not use this file except in compliance with
2230 -+ * the License. You may obtain a copy of the License at
2231 -+ *
2232 -+ * http://www.apache.org/licenses/LICENSE-2.0
2233 -+ *
2234 -+ * Unless required by applicable law or agreed to in writing, software
2235 -+ * distributed under the License is distributed on an "AS IS" BASIS,
2236 -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2237 -+ * See the License for the specific language governing permissions and
2238 -+ * limitations under the License.
2239 -+ *
2240 -+ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
2241 -+ * Licensed under the same terms as the rest of Apache.
2242 -+ *
2243 -+ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
2244 -+ * Licensed under the same terms as the rest of Apache.
2245 -+ */
2246 -+
2247 -+#include "apr.h"
2248 -+#include "apr_portable.h"
2249 -+#include "apr_strings.h"
2250 -+#include "apr_thread_proc.h"
2251 -+#include "apr_signal.h"
2252 -+
2253 -+# define _DBG(text,par...) \
2254 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \
2255 -+ "(itkmpm: pid=%d uid=%d, gid=%d) %s(): " text, \
2256 -+ getpid(), getuid(), getgid(), __FUNCTION__, par)
2257 -+
2258 -+#define APR_WANT_STDIO
2259 -+#define APR_WANT_STRFUNC
2260 -+#include "apr_want.h"
2261 -+
2262 -+#if APR_HAVE_UNISTD_H
2263 -+#include <unistd.h>
2264 -+#endif
2265 -+#if APR_HAVE_SYS_TYPES_H
2266 -+#include <sys/types.h>
2267 -+#endif
2268 -+
2269 -+#define CORE_PRIVATE
2270 -+
2271 -+#include "ap_config.h"
2272 -+#include "httpd.h"
2273 -+#include "mpm_default.h"
2274 -+#include "http_main.h"
2275 -+#include "http_log.h"
2276 -+#include "http_config.h"
2277 -+#include "http_core.h" /* for get_remote_host */
2278 -+#include "http_connection.h"
2279 -+#include "http_request.h" /* for ap_hook_post_perdir_config */
2280 -+#include "scoreboard.h"
2281 -+#include "ap_mpm.h"
2282 -+#include "unixd.h"
2283 -+#include "mpm_common.h"
2284 -+#include "ap_listen.h"
2285 -+#include "ap_mmn.h"
2286 -+#include "apr_poll.h"
2287 -+
2288 -+#ifdef HAVE_BSTRING_H
2289 -+#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
2290 -+#endif
2291 -+#ifdef HAVE_TIME_H
2292 -+#include <time.h>
2293 -+#endif
2294 -+#ifdef HAVE_SYS_PROCESSOR_H
2295 -+#include <sys/processor.h> /* for bindprocessor() */
2296 -+#endif
2297 -+
2298 -+#if HAVE_LIBCAP
2299 -+#include <sys/capability.h>
2300 -+#endif
2301 -+
2302 -+#include <signal.h>
2303 -+#include <sys/times.h>
2304 -+
2305 -+/* Limit on the total --- clients will be locked out if more servers than
2306 -+ * this are needed. It is intended solely to keep the server from crashing
2307 -+ * when things get out of hand.
2308 -+ *
2309 -+ * We keep a hard maximum number of servers, for two reasons --- first off,
2310 -+ * in case something goes seriously wrong, we want to stop the fork bomb
2311 -+ * short of actually crashing the machine we're running on by filling some
2312 -+ * kernel table. Secondly, it keeps the size of the scoreboard file small
2313 -+ * enough that we can read the whole thing without worrying too much about
2314 -+ * the overhead.
2315 -+ */
2316 -+#ifndef DEFAULT_SERVER_LIMIT
2317 -+#define DEFAULT_SERVER_LIMIT 256
2318 -+#endif
2319 -+
2320 -+/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
2321 -+ * some sort of compile-time limit to help catch typos.
2322 -+ */
2323 -+#ifndef MAX_SERVER_LIMIT
2324 -+#define MAX_SERVER_LIMIT 200000
2325 -+#endif
2326 -+
2327 -+#ifndef HARD_THREAD_LIMIT
2328 -+#define HARD_THREAD_LIMIT 1
2329 -+#endif
2330 -+
2331 -+/* config globals */
2332 -+
2333 -+int ap_threads_per_child=0; /* Worker threads per child */
2334 -+static apr_proc_mutex_t *accept_mutex;
2335 -+static int ap_daemons_to_start=0;
2336 -+static int ap_daemons_min_free=0;
2337 -+static int ap_daemons_max_free=0;
2338 -+static int ap_daemons_limit=0; /* MaxClients */
2339 -+static int server_limit = DEFAULT_SERVER_LIMIT;
2340 -+static int first_server_limit = 0;
2341 -+static int changed_limit_at_restart;
2342 -+static int mpm_state = AP_MPMQ_STARTING;
2343 -+static ap_pod_t *pod;
2344 -+
2345 -+/*
2346 -+ * The max child slot ever assigned, preserved across restarts. Necessary
2347 -+ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
2348 -+ * use this value to optimize routines that have to scan the entire scoreboard.
2349 -+ */
2350 -+int ap_max_daemons_limit = -1;
2351 -+server_rec *ap_server_conf;
2352 -+
2353 -+/* one_process --- debugging mode variable; can be set from the command line
2354 -+ * with the -X flag. If set, this gets you the child_main loop running
2355 -+ * in the process which originally started up (no detach, no make_child),
2356 -+ * which is a pretty nice debugging environment. (You'll get a SIGHUP
2357 -+ * early in standalone_main; just continue through. This is the server
2358 -+ * trying to kill off any child processes which it might have lying
2359 -+ * around --- Apache doesn't keep track of their pids, it just sends
2360 -+ * SIGHUP to the process group, ignoring it in the root process.
2361 -+ * Continue through and you'll be fine.).
2362 -+ */
2363 -+
2364 -+static int one_process = 0;
2365 -+
2366 -+static apr_pool_t *pconf; /* Pool for config stuff */
2367 -+static apr_pool_t *pchild; /* Pool for httpd child stuff */
2368 -+
2369 -+static pid_t ap_my_pid; /* it seems silly to call getpid all the time */
2370 -+static pid_t parent_pid;
2371 -+#ifndef MULTITHREAD
2372 -+static int my_child_num;
2373 -+#endif
2374 -+ap_generation_t volatile ap_my_generation=0;
2375 -+
2376 -+#ifdef TPF
2377 -+int tpf_child = 0;
2378 -+char tpf_server_name[INETD_SERVNAME_LENGTH+1];
2379 -+#endif /* TPF */
2380 -+
2381 -+static volatile int die_now = 0;
2382 -+
2383 -+#define UNSET_NICE_VALUE 100
2384 -+
2385 -+typedef struct
2386 -+{
2387 -+ uid_t uid;
2388 -+ gid_t gid;
2389 -+ char *username;
2390 -+ int nice_value;
2391 -+} itk_per_dir_conf;
2392 -+
2393 -+typedef struct
2394 -+{
2395 -+ int max_clients_vhost;
2396 -+} itk_server_conf;
2397 -+
2398 -+module AP_MODULE_DECLARE_DATA mpm_itk_module;
2399 -+
2400 -+#ifdef GPROF
2401 -+/*
2402 -+ * change directory for gprof to plop the gmon.out file
2403 -+ * configure in httpd.conf:
2404 -+ * GprofDir $RuntimeDir/ -> $ServerRoot/$RuntimeDir/gmon.out
2405 -+ * GprofDir $RuntimeDir/% -> $ServerRoot/$RuntimeDir/gprof.$pid/gmon.out
2406 -+ */
2407 -+static void chdir_for_gprof(void)
2408 -+{
2409 -+ core_server_config *sconf =
2410 -+ ap_get_module_config(ap_server_conf->module_config, &core_module);
2411 -+ char *dir = sconf->gprof_dir;
2412 -+ const char *use_dir;
2413 -+
2414 -+ if(dir) {
2415 -+ apr_status_t res;
2416 -+ char *buf = NULL ;
2417 -+ int len = strlen(sconf->gprof_dir) - 1;
2418 -+ if(*(dir + len) == '%') {
2419 -+ dir[len] = '\0';
2420 -+ buf = ap_append_pid(pconf, dir, "gprof.");
2421 -+ }
2422 -+ use_dir = ap_server_root_relative(pconf, buf ? buf : dir);
2423 -+ res = apr_dir_make(use_dir,
2424 -+ APR_UREAD | APR_UWRITE | APR_UEXECUTE |
2425 -+ APR_GREAD | APR_GEXECUTE |
2426 -+ APR_WREAD | APR_WEXECUTE, pconf);
2427 -+ if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) {
2428 -+ ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf,
2429 -+ "gprof: error creating directory %s", dir);
2430 -+ }
2431 -+ }
2432 -+ else {
2433 -+ use_dir = ap_server_root_relative(pconf, DEFAULT_REL_RUNTIMEDIR);
2434 -+ }
2435 -+
2436 -+ chdir(use_dir);
2437 -+}
2438 -+#else
2439 -+#define chdir_for_gprof()
2440 -+#endif
2441 -+
2442 -+/* XXX - I don't know if TPF will ever use this module or not, so leave
2443 -+ * the ap_check_signals calls in but disable them - manoj */
2444 -+#define ap_check_signals()
2445 -+
2446 -+/* a clean exit from a child with proper cleanup */
2447 -+static void clean_child_exit(int code) __attribute__ ((noreturn));
2448 -+static void clean_child_exit(int code)
2449 -+{
2450 -+ mpm_state = AP_MPMQ_STOPPING;
2451 -+
2452 -+ if (pchild) {
2453 -+ apr_pool_destroy(pchild);
2454 -+ }
2455 -+ ap_mpm_pod_close(pod);
2456 -+ chdir_for_gprof();
2457 -+ exit(code);
2458 -+}
2459 -+
2460 -+static void accept_mutex_on(void)
2461 -+{
2462 -+ apr_status_t rv = apr_proc_mutex_lock(accept_mutex);
2463 -+ if (rv != APR_SUCCESS) {
2464 -+ const char *msg = "couldn't grab the accept mutex";
2465 -+
2466 -+ if (ap_my_generation !=
2467 -+ ap_scoreboard_image->global->running_generation) {
2468 -+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
2469 -+ clean_child_exit(0);
2470 -+ }
2471 -+ else {
2472 -+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
2473 -+ exit(APEXIT_CHILDFATAL);
2474 -+ }
2475 -+ }
2476 -+}
2477 -+
2478 -+static void accept_mutex_off(void)
2479 -+{
2480 -+ apr_status_t rv = apr_proc_mutex_unlock(accept_mutex);
2481 -+ if (rv != APR_SUCCESS) {
2482 -+ const char *msg = "couldn't release the accept mutex";
2483 -+
2484 -+ if (ap_my_generation !=
2485 -+ ap_scoreboard_image->global->running_generation) {
2486 -+ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg);
2487 -+ /* don't exit here... we have a connection to
2488 -+ * process, after which point we'll see that the
2489 -+ * generation changed and we'll exit cleanly
2490 -+ */
2491 -+ }
2492 -+ else {
2493 -+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg);
2494 -+ exit(APEXIT_CHILDFATAL);
2495 -+ }
2496 -+ }
2497 -+}
2498 -+
2499 -+/* On some architectures it's safe to do unserialized accept()s in the single
2500 -+ * Listen case. But it's never safe to do it in the case where there's
2501 -+ * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
2502 -+ * when it's safe in the single Listen case.
2503 -+ */
2504 -+#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT
2505 -+#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0)
2506 -+#else
2507 -+#define SAFE_ACCEPT(stmt) do {stmt;} while(0)
2508 -+#endif
2509 -+
2510 -+AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
2511 -+{
2512 -+ switch(query_code){
2513 -+ case AP_MPMQ_MAX_DAEMON_USED:
2514 -+ *result = ap_daemons_limit;
2515 -+ return APR_SUCCESS;
2516 -+ case AP_MPMQ_IS_THREADED:
2517 -+ *result = AP_MPMQ_NOT_SUPPORTED;
2518 -+ return APR_SUCCESS;
2519 -+ case AP_MPMQ_IS_FORKED:
2520 -+ *result = AP_MPMQ_DYNAMIC;
2521 -+ return APR_SUCCESS;
2522 -+ case AP_MPMQ_HARD_LIMIT_DAEMONS:
2523 -+ *result = server_limit;
2524 -+ return APR_SUCCESS;
2525 -+ case AP_MPMQ_HARD_LIMIT_THREADS:
2526 -+ *result = HARD_THREAD_LIMIT;
2527 -+ return APR_SUCCESS;
2528 -+ case AP_MPMQ_MAX_THREADS:
2529 -+ *result = 0;
2530 -+ return APR_SUCCESS;
2531 -+ case AP_MPMQ_MIN_SPARE_DAEMONS:
2532 -+ *result = ap_daemons_min_free;
2533 -+ return APR_SUCCESS;
2534 -+ case AP_MPMQ_MIN_SPARE_THREADS:
2535 -+ *result = 0;
2536 -+ return APR_SUCCESS;
2537 -+ case AP_MPMQ_MAX_SPARE_DAEMONS:
2538 -+ *result = ap_daemons_max_free;
2539 -+ return APR_SUCCESS;
2540 -+ case AP_MPMQ_MAX_SPARE_THREADS:
2541 -+ *result = 0;
2542 -+ return APR_SUCCESS;
2543 -+ case AP_MPMQ_MAX_REQUESTS_DAEMON:
2544 -+ *result = ap_max_requests_per_child;
2545 -+ return APR_SUCCESS;
2546 -+ case AP_MPMQ_MAX_DAEMONS:
2547 -+ *result = server_limit;
2548 -+ return APR_SUCCESS;
2549 -+ case AP_MPMQ_MPM_STATE:
2550 -+ *result = mpm_state;
2551 -+ return APR_SUCCESS;
2552 -+ }
2553 -+ return APR_ENOTIMPL;
2554 -+}
2555 -+
2556 -+#if defined(NEED_WAITPID)
2557 -+/*
2558 -+ Systems without a real waitpid sometimes lose a child's exit while waiting
2559 -+ for another. Search through the scoreboard for missing children.
2560 -+ */
2561 -+int reap_children(int *exitcode, apr_exit_why_e *status)
2562 -+{
2563 -+ int n, pid;
2564 -+
2565 -+ for (n = 0; n < ap_max_daemons_limit; ++n) {
2566 -+ if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&
2567 -+ kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
2568 -+ ap_update_child_status_from_indexes(n, 0, SERVER_DEAD, NULL);
2569 -+ /* just mark it as having a successful exit status */
2570 -+ *status = APR_PROC_EXIT;
2571 -+ *exitcode = 0;
2572 -+ return(pid);
2573 -+ }
2574 -+ }
2575 -+ return 0;
2576 -+}
2577 -+#endif
2578 -+
2579 -+/*****************************************************************
2580 -+ * Connection structures and accounting...
2581 -+ */
2582 -+
2583 -+static void just_die(int sig)
2584 -+{
2585 -+ clean_child_exit(0);
2586 -+}
2587 -+
2588 -+static void stop_listening(int sig)
2589 -+{
2590 -+ ap_close_listeners();
2591 -+
2592 -+ /* For a graceful stop, we want the child to exit when done */
2593 -+ die_now = 1;
2594 -+}
2595 -+
2596 -+/* volatile just in case */
2597 -+static int volatile shutdown_pending;
2598 -+static int volatile restart_pending;
2599 -+static int volatile is_graceful;
2600 -+
2601 -+static void sig_term(int sig)
2602 -+{
2603 -+ if (shutdown_pending == 1) {
2604 -+ /* Um, is this _probably_ not an error, if the user has
2605 -+ * tried to do a shutdown twice quickly, so we won't
2606 -+ * worry about reporting it.
2607 -+ */
2608 -+ return;
2609 -+ }
2610 -+ shutdown_pending = 1;
2611 -+ is_graceful = (sig == AP_SIG_GRACEFUL_STOP);
2612 -+}
2613 -+
2614 -+/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL
2615 -+ * in the parent process, unless running in ONE_PROCESS mode
2616 -+ */
2617 -+static void restart(int sig)
2618 -+{
2619 -+ if (restart_pending == 1) {
2620 -+ /* Probably not an error - don't bother reporting it */
2621 -+ return;
2622 -+ }
2623 -+ restart_pending = 1;
2624 -+ is_graceful = (sig == AP_SIG_GRACEFUL);
2625 -+}
2626 -+
2627 -+static void set_signals(void)
2628 -+{
2629 -+#ifndef NO_USE_SIGACTION
2630 -+ struct sigaction sa;
2631 -+#endif
2632 -+
2633 -+ if (!one_process) {
2634 -+ ap_fatal_signal_setup(ap_server_conf, pconf);
2635 -+ }
2636 -+
2637 -+#ifndef NO_USE_SIGACTION
2638 -+ sigemptyset(&sa.sa_mask);
2639 -+ sa.sa_flags = 0;
2640 -+
2641 -+ sa.sa_handler = sig_term;
2642 -+ if (sigaction(SIGTERM, &sa, NULL) < 0)
2643 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)");
2644 -+#ifdef AP_SIG_GRACEFUL_STOP
2645 -+ if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
2646 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
2647 -+ "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
2648 -+#endif
2649 -+#ifdef SIGINT
2650 -+ if (sigaction(SIGINT, &sa, NULL) < 0)
2651 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)");
2652 -+#endif
2653 -+#ifdef SIGXCPU
2654 -+ sa.sa_handler = SIG_DFL;
2655 -+ if (sigaction(SIGXCPU, &sa, NULL) < 0)
2656 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)");
2657 -+#endif
2658 -+#ifdef SIGXFSZ
2659 -+ sa.sa_handler = SIG_DFL;
2660 -+ if (sigaction(SIGXFSZ, &sa, NULL) < 0)
2661 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)");
2662 -+#endif
2663 -+#ifdef SIGPIPE
2664 -+ sa.sa_handler = SIG_IGN;
2665 -+ if (sigaction(SIGPIPE, &sa, NULL) < 0)
2666 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)");
2667 -+#endif
2668 -+
2669 -+ /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
2670 -+ * processing one
2671 -+ */
2672 -+ sigaddset(&sa.sa_mask, SIGHUP);
2673 -+ sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
2674 -+ sa.sa_handler = restart;
2675 -+ if (sigaction(SIGHUP, &sa, NULL) < 0)
2676 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)");
2677 -+ if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
2678 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")");
2679 -+#else
2680 -+ if (!one_process) {
2681 -+#ifdef SIGXCPU
2682 -+ apr_signal(SIGXCPU, SIG_DFL);
2683 -+#endif /* SIGXCPU */
2684 -+#ifdef SIGXFSZ
2685 -+ apr_signal(SIGXFSZ, SIG_DFL);
2686 -+#endif /* SIGXFSZ */
2687 -+ }
2688 -+
2689 -+ apr_signal(SIGTERM, sig_term);
2690 -+#ifdef SIGHUP
2691 -+ apr_signal(SIGHUP, restart);
2692 -+#endif /* SIGHUP */
2693 -+#ifdef AP_SIG_GRACEFUL
2694 -+ apr_signal(AP_SIG_GRACEFUL, restart);
2695 -+#endif /* AP_SIG_GRACEFUL */
2696 -+#ifdef AP_SIG_GRACEFUL_STOP
2697 -+ apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
2698 -+#endif /* AP_SIG_GRACEFUL */
2699 -+#ifdef SIGPIPE
2700 -+ apr_signal(SIGPIPE, SIG_IGN);
2701 -+#endif /* SIGPIPE */
2702 -+
2703 -+#endif
2704 -+}
2705 -+
2706 -+/*****************************************************************
2707 -+ * Child process main loop.
2708 -+ * The following vars are static to avoid getting clobbered by longjmp();
2709 -+ * they are really private to child_main.
2710 -+ */
2711 -+
2712 -+static int requests_this_child;
2713 -+static int num_listensocks = 0;
2714 -+
2715 -+
2716 -+int ap_graceful_stop_signalled(void)
2717 -+{
2718 -+ /* not ever called anymore... */
2719 -+ return 0;
2720 -+}
2721 -+
2722 -+
2723 -+static void child_main(int child_num_arg)
2724 -+{
2725 -+ apr_pool_t *ptrans;
2726 -+ apr_allocator_t *allocator;
2727 -+ apr_status_t status;
2728 -+ int i;
2729 -+ ap_listen_rec *lr;
2730 -+ apr_pollset_t *pollset;
2731 -+ ap_sb_handle_t *sbh;
2732 -+ apr_bucket_alloc_t *bucket_alloc;
2733 -+ int last_poll_idx = 0;
2734 -+
2735 -+#if HAVE_LIBCAP
2736 -+ cap_t caps;
2737 -+ cap_value_t suidcaps[] = {
2738 -+ CAP_SETUID,
2739 -+ CAP_SETGID,
2740 -+ CAP_DAC_READ_SEARCH,
2741 -+ CAP_SYS_NICE,
2742 -+ };
2743 -+#endif
2744 -+
2745 -+ mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
2746 -+ * child initializes
2747 -+ */
2748 -+
2749 -+ my_child_num = child_num_arg;
2750 -+ ap_my_pid = getpid();
2751 -+ requests_this_child = 0;
2752 -+
2753 -+ ap_fatal_signal_child_setup(ap_server_conf);
2754 -+
2755 -+ /* Get a sub context for global allocations in this child, so that
2756 -+ * we can have cleanups occur when the child exits.
2757 -+ */
2758 -+ apr_allocator_create(&allocator);
2759 -+ apr_allocator_max_free_set(allocator, ap_max_mem_free);
2760 -+ apr_pool_create_ex(&pchild, pconf, NULL, allocator);
2761 -+ apr_allocator_owner_set(allocator, pchild);
2762 -+
2763 -+ apr_pool_create(&ptrans, pchild);
2764 -+ apr_pool_tag(ptrans, "transaction");
2765 -+
2766 -+ /* needs to be done before we switch UIDs so we have permissions */
2767 -+ ap_reopen_scoreboard(pchild, NULL, 0);
2768 -+ status = apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild);
2769 -+ if (status != APR_SUCCESS) {
2770 -+ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf,
2771 -+ "Couldn't initialize cross-process lock in child "
2772 -+ "(%s) (%d)", ap_lock_fname, ap_accept_lock_mech);
2773 -+ clean_child_exit(APEXIT_CHILDFATAL);
2774 -+ }
2775 -+
2776 -+ ap_run_child_init(pchild, ap_server_conf);
2777 -+
2778 -+ ap_create_sb_handle(&sbh, pchild, my_child_num, 0);
2779 -+
2780 -+ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
2781 -+
2782 -+ /* Set up the pollfd array */
2783 -+ /* ### check the status */
2784 -+ (void) apr_pollset_create(&pollset, num_listensocks, pchild, 0);
2785 -+
2786 -+ for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) {
2787 -+ apr_pollfd_t pfd = { 0 };
2788 -+
2789 -+ pfd.desc_type = APR_POLL_SOCKET;
2790 -+ pfd.desc.s = lr->sd;
2791 -+ pfd.reqevents = APR_POLLIN;
2792 -+ pfd.client_data = lr;
2793 -+
2794 -+ /* ### check the status */
2795 -+ (void) apr_pollset_add(pollset, &pfd);
2796 -+ }
2797 -+
2798 -+#if HAVE_LIBCAP
2799 -+ /* Drop as many privileges as we can. We'll still
2800 -+ * access files with uid=0, and we can setuid() to anything, but
2801 -+ * at least there's tons of other evilness (like loading kernel
2802 -+ * modules) we can't do directly. (The setuid() capability will
2803 -+ * go away automatically when we setuid() or exec() -- the former
2804 -+ * is likely to come first.)
2805 -+ */
2806 -+ caps = cap_init();
2807 -+ cap_clear(caps);
2808 -+ cap_set_flag(caps, CAP_PERMITTED, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET);
2809 -+ cap_set_flag(caps, CAP_EFFECTIVE, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET);
2810 -+ cap_set_proc(caps);
2811 -+ cap_free(caps);
2812 -+#endif
2813 -+
2814 -+ mpm_state = AP_MPMQ_RUNNING;
2815 -+
2816 -+ bucket_alloc = apr_bucket_alloc_create(pchild);
2817 -+
2818 -+ /* die_now is set when AP_SIG_GRACEFUL is received in the child;
2819 -+ * shutdown_pending is set when SIGTERM is received when running
2820 -+ * in single process mode. */
2821 -+ while (!die_now && !shutdown_pending) {
2822 -+ conn_rec *current_conn;
2823 -+ void *csd;
2824 -+
2825 -+ /*
2826 -+ * (Re)initialize this child to a pre-connection state.
2827 -+ */
2828 -+
2829 -+ apr_pool_clear(ptrans);
2830 -+
2831 -+ if ((ap_max_requests_per_child > 0
2832 -+ && requests_this_child++ >= ap_max_requests_per_child)) {
2833 -+ clean_child_exit(0);
2834 -+ }
2835 -+
2836 -+ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
2837 -+
2838 -+ /*
2839 -+ * Wait for an acceptable connection to arrive.
2840 -+ */
2841 -+
2842 -+ /* Lock around "accept", if necessary */
2843 -+ SAFE_ACCEPT(accept_mutex_on());
2844 -+
2845 -+ if (num_listensocks == 1) {
2846 -+ /* There is only one listener record, so refer to that one. */
2847 -+ lr = ap_listeners;
2848 -+ }
2849 -+ else {
2850 -+ /* multiple listening sockets - need to poll */
2851 -+ for (;;) {
2852 -+ apr_int32_t numdesc;
2853 -+ const apr_pollfd_t *pdesc;
2854 -+
2855 -+ /* timeout == -1 == wait forever */
2856 -+ status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc);
2857 -+ if (status != APR_SUCCESS) {
2858 -+ if (APR_STATUS_IS_EINTR(status)) {
2859 -+ if (one_process && shutdown_pending) {
2860 -+ return;
2861 -+ }
2862 -+ else if (die_now) {
2863 -+ /* In graceful stop/restart; drop the mutex
2864 -+ * and terminate the child. */
2865 -+ SAFE_ACCEPT(accept_mutex_off());
2866 -+ clean_child_exit(0);
2867 -+ }
2868 -+ continue;
2869 -+ }
2870 -+ /* Single Unix documents select as returning errnos
2871 -+ * EBADF, EINTR, and EINVAL... and in none of those
2872 -+ * cases does it make sense to continue. In fact
2873 -+ * on Linux 2.0.x we seem to end up with EFAULT
2874 -+ * occasionally, and we'd loop forever due to it.
2875 -+ */
2876 -+ ap_log_error(APLOG_MARK, APLOG_ERR, status,
2877 -+ ap_server_conf, "apr_pollset_poll: (listen)");
2878 -+ SAFE_ACCEPT(accept_mutex_off());
2879 -+ clean_child_exit(1);
2880 -+ }
2881 -+
2882 -+ /* We can always use pdesc[0], but sockets at position N
2883 -+ * could end up completely starved of attention in a very
2884 -+ * busy server. Therefore, we round-robin across the
2885 -+ * returned set of descriptors. While it is possible that
2886 -+ * the returned set of descriptors might flip around and
2887 -+ * continue to starve some sockets, we happen to know the
2888 -+ * internal pollset implementation retains ordering
2889 -+ * stability of the sockets. Thus, the round-robin should
2890 -+ * ensure that a socket will eventually be serviced.
2891 -+ */
2892 -+ if (last_poll_idx >= numdesc)
2893 -+ last_poll_idx = 0;
2894 -+
2895 -+ /* Grab a listener record from the client_data of the poll
2896 -+ * descriptor, and advance our saved index to round-robin
2897 -+ * the next fetch.
2898 -+ *
2899 -+ * ### hmm... this descriptor might have POLLERR rather
2900 -+ * ### than POLLIN
2901 -+ */
2902 -+ lr = pdesc[last_poll_idx++].client_data;
2903 -+ goto got_fd;
2904 -+ }
2905 -+ }
2906 -+ got_fd:
2907 -+ /* if we accept() something we don't want to die, so we have to
2908 -+ * defer the exit
2909 -+ */
2910 -+ status = lr->accept_func(&csd, lr, ptrans);
2911 -+
2912 -+ SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
2913 -+
2914 -+ if (status == APR_EGENERAL) {
2915 -+ /* resource shortage or should-not-occur occured */
2916 -+ clean_child_exit(1);
2917 -+ }
2918 -+ else if (status != APR_SUCCESS) {
2919 -+ continue;
2920 -+ }
2921 -+
2922 -+ /*
2923 -+ * We now have a connection, so set it up with the appropriate
2924 -+ * socket options, file descriptors, and read/write buffers.
2925 -+ */
2926 -+
2927 -+ {
2928 -+ pid_t pid = fork(), child_pid;
2929 -+ int status;
2930 -+ switch (pid) {
2931 -+ case -1:
2932 -+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "fork: Unable to fork new process");
2933 -+ break;
2934 -+ case 0: /* child */
2935 -+ apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild);
2936 -+ current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc);
2937 -+ if (current_conn) {
2938 -+ ap_process_connection(current_conn, csd);
2939 -+ ap_lingering_close(current_conn);
2940 -+ }
2941 -+ exit(0);
2942 -+ default: /* parent; just wait for child to be done */
2943 -+ do {
2944 -+ child_pid = waitpid(pid, &status, 0);
2945 -+ } while (child_pid == -1 && errno == EINTR);
2946 -+
2947 -+ if (child_pid != pid || !WIFEXITED(status)) {
2948 -+ if (WIFSIGNALED(status)) {
2949 -+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child died with signal %u", WTERMSIG(status));
2950 -+ } else if (WEXITSTATUS(status) != 0) {
2951 -+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child exited with non-zero exit status %u", WEXITSTATUS(status));
2952 -+ } else {
2953 -+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "waitpid() failed");
2954 -+ }
2955 -+ clean_child_exit(1);
2956 -+ }
2957 -+ break;
2958 -+ }
2959 -+ }
2960 -+
2961 -+ /* Check the pod and the generation number after processing a
2962 -+ * connection so that we'll go away if a graceful restart occurred
2963 -+ * while we were processing the connection or we are the lucky
2964 -+ * idle server process that gets to die.
2965 -+ */
2966 -+ if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */
2967 -+ die_now = 1;
2968 -+ }
2969 -+ else if (ap_my_generation !=
2970 -+ ap_scoreboard_image->global->running_generation) { /* restart? */
2971 -+ /* yeah, this could be non-graceful restart, in which case the
2972 -+ * parent will kill us soon enough, but why bother checking?
2973 -+ */
2974 -+ die_now = 1;
2975 -+ }
2976 -+
2977 -+ /* if we have already setuid(), die (we can't be used anyhow) */
2978 -+ if (getuid())
2979 -+ die_now = 1;
2980 -+ }
2981 -+ clean_child_exit(0);
2982 -+}
2983 -+
2984 -+
2985 -+static int make_child(server_rec *s, int slot)
2986 -+{
2987 -+ int pid;
2988 -+
2989 -+ if (slot + 1 > ap_max_daemons_limit) {
2990 -+ ap_max_daemons_limit = slot + 1;
2991 -+ }
2992 -+
2993 -+ if (one_process) {
2994 -+ apr_signal(SIGHUP, sig_term);
2995 -+ /* Don't catch AP_SIG_GRACEFUL in ONE_PROCESS mode :) */
2996 -+ apr_signal(SIGINT, sig_term);
2997 -+#ifdef SIGQUIT
2998 -+ apr_signal(SIGQUIT, SIG_DFL);
2999 -+#endif
3000 -+ apr_signal(SIGTERM, sig_term);
3001 -+ child_main(slot);
3002 -+ return 0;
3003 -+ }
3004 -+
3005 -+ (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING,
3006 -+ (request_rec *) NULL);
3007 -+
3008 -+
3009 -+#ifdef _OSD_POSIX
3010 -+ /* BS2000 requires a "special" version of fork() before a setuid() call */
3011 -+ if ((pid = os_fork(unixd_config.user_name)) == -1) {
3012 -+#elif defined(TPF)
3013 -+ if ((pid = os_fork(s, slot)) == -1) {
3014 -+#else
3015 -+ if ((pid = fork()) == -1) {
3016 -+#endif
3017 -+ ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process");
3018 -+
3019 -+ /* fork didn't succeed. Fix the scoreboard or else
3020 -+ * it will say SERVER_STARTING forever and ever
3021 -+ */
3022 -+ (void) ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD,
3023 -+ (request_rec *) NULL);
3024 -+
3025 -+ /* In case system resources are maxxed out, we don't want
3026 -+ * Apache running away with the CPU trying to fork over and
3027 -+ * over and over again.
3028 -+ */
3029 -+ sleep(10);
3030 -+
3031 -+ return -1;
3032 -+ }
3033 -+
3034 -+ if (!pid) {
3035 -+#ifdef HAVE_BINDPROCESSOR
3036 -+ /* by default AIX binds to a single processor
3037 -+ * this bit unbinds children which will then bind to another cpu
3038 -+ */
3039 -+ int status = bindprocessor(BINDPROCESS, (int)getpid(),
3040 -+ PROCESSOR_CLASS_ANY);
3041 -+ if (status != OK) {
3042 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
3043 -+ ap_server_conf, "processor unbind failed %d", status);
3044 -+ }
3045 -+#endif
3046 -+ RAISE_SIGSTOP(MAKE_CHILD);
3047 -+ AP_MONCONTROL(1);
3048 -+ /* Disable the parent's signal handlers and set up proper handling in
3049 -+ * the child.
3050 -+ */
3051 -+ apr_signal(SIGHUP, just_die);
3052 -+ apr_signal(SIGTERM, just_die);
3053 -+ /* The child process just closes listeners on AP_SIG_GRACEFUL.
3054 -+ * The pod is used for signalling the graceful restart.
3055 -+ */
3056 -+ apr_signal(AP_SIG_GRACEFUL, stop_listening);
3057 -+ child_main(slot);
3058 -+ }
3059 -+
3060 -+ ap_scoreboard_image->parent[slot].pid = pid;
3061 -+
3062 -+ return 0;
3063 -+}
3064 -+
3065 -+
3066 -+/* start up a bunch of children */
3067 -+static void startup_children(int number_to_start)
3068 -+{
3069 -+ int i;
3070 -+
3071 -+ for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
3072 -+ if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
3073 -+ continue;
3074 -+ }
3075 -+ if (make_child(ap_server_conf, i) < 0) {
3076 -+ break;
3077 -+ }
3078 -+ --number_to_start;
3079 -+ }
3080 -+}
3081 -+
3082 -+
3083 -+/*
3084 -+ * idle_spawn_rate is the number of children that will be spawned on the
3085 -+ * next maintenance cycle if there aren't enough idle servers. It is
3086 -+ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
3087 -+ * without the need to spawn.
3088 -+ */
3089 -+static int idle_spawn_rate = 1;
3090 -+#ifndef MAX_SPAWN_RATE
3091 -+#define MAX_SPAWN_RATE (32)
3092 -+#endif
3093 -+static int hold_off_on_exponential_spawning;
3094 -+
3095 -+static void perform_idle_server_maintenance(apr_pool_t *p)
3096 -+{
3097 -+ int i;
3098 -+ int to_kill;
3099 -+ int idle_count;
3100 -+ worker_score *ws;
3101 -+ int free_length;
3102 -+ int free_slots[MAX_SPAWN_RATE];
3103 -+ int last_non_dead;
3104 -+ int total_non_dead;
3105 -+
3106 -+ /* initialize the free_list */
3107 -+ free_length = 0;
3108 -+
3109 -+ to_kill = -1;
3110 -+ idle_count = 0;
3111 -+ last_non_dead = -1;
3112 -+ total_non_dead = 0;
3113 -+
3114 -+ for (i = 0; i < ap_daemons_limit; ++i) {
3115 -+ int status;
3116 -+
3117 -+ if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
3118 -+ break;
3119 -+ ws = &ap_scoreboard_image->servers[i][0];
3120 -+ status = ws->status;
3121 -+ if (status == SERVER_DEAD) {
3122 -+ /* try to keep children numbers as low as possible */
3123 -+ if (free_length < idle_spawn_rate) {
3124 -+ free_slots[free_length] = i;
3125 -+ ++free_length;
3126 -+ }
3127 -+ }
3128 -+ else {
3129 -+ /* We consider a starting server as idle because we started it
3130 -+ * at least a cycle ago, and if it still hasn't finished starting
3131 -+ * then we're just going to swamp things worse by forking more.
3132 -+ * So we hopefully won't need to fork more if we count it.
3133 -+ * This depends on the ordering of SERVER_READY and SERVER_STARTING.
3134 -+ */
3135 -+ if (status <= SERVER_READY) {
3136 -+ ++ idle_count;
3137 -+ /* always kill the highest numbered child if we have to...
3138 -+ * no really well thought out reason ... other than observing
3139 -+ * the server behaviour under linux where lower numbered children
3140 -+ * tend to service more hits (and hence are more likely to have
3141 -+ * their data in cpu caches).
3142 -+ */
3143 -+ to_kill = i;
3144 -+ }
3145 -+
3146 -+ ++total_non_dead;
3147 -+ last_non_dead = i;
3148 -+ }
3149 -+ }
3150 -+ ap_max_daemons_limit = last_non_dead + 1;
3151 -+ if (idle_count > ap_daemons_max_free) {
3152 -+ /* kill off one child... we use the pod because that'll cause it to
3153 -+ * shut down gracefully, in case it happened to pick up a request
3154 -+ * while we were counting
3155 -+ */
3156 -+ ap_mpm_pod_signal(pod);
3157 -+ idle_spawn_rate = 1;
3158 -+ }
3159 -+ else if (idle_count < ap_daemons_min_free) {
3160 -+ /* terminate the free list */
3161 -+ if (free_length == 0) {
3162 -+ /* only report this condition once */
3163 -+ static int reported = 0;
3164 -+
3165 -+ if (!reported) {
3166 -+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
3167 -+ "server reached MaxClients setting, consider"
3168 -+ " raising the MaxClients setting");
3169 -+ reported = 1;
3170 -+ }
3171 -+ idle_spawn_rate = 1;
3172 -+ }
3173 -+ else {
3174 -+ if (idle_spawn_rate >= 8) {
3175 -+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
3176 -+ "server seems busy, (you may need "
3177 -+ "to increase StartServers, or Min/MaxSpareServers), "
3178 -+ "spawning %d children, there are %d idle, and "
3179 -+ "%d total children", idle_spawn_rate,
3180 -+ idle_count, total_non_dead);
3181 -+ }
3182 -+ for (i = 0; i < free_length; ++i) {
3183 -+#ifdef TPF
3184 -+ if (make_child(ap_server_conf, free_slots[i]) == -1) {
3185 -+ if(free_length == 1) {
3186 -+ shutdown_pending = 1;
3187 -+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, ap_server_conf,
3188 -+ "No active child processes: shutting down");
3189 -+ }
3190 -+ }
3191 -+#else
3192 -+ make_child(ap_server_conf, free_slots[i]);
3193 -+#endif /* TPF */
3194 -+ }
3195 -+ /* the next time around we want to spawn twice as many if this
3196 -+ * wasn't good enough, but not if we've just done a graceful
3197 -+ */
3198 -+ if (hold_off_on_exponential_spawning) {
3199 -+ --hold_off_on_exponential_spawning;
3200 -+ }
3201 -+ else if (idle_spawn_rate < MAX_SPAWN_RATE) {
3202 -+ idle_spawn_rate *= 2;
3203 -+ }
3204 -+ }
3205 -+ }
3206 -+ else {
3207 -+ idle_spawn_rate = 1;
3208 -+ }
3209 -+}
3210 -+
3211 -+/*****************************************************************
3212 -+ * Executive routines.
3213 -+ */
3214 -+
3215 -+int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
3216 -+{
3217 -+ int index;
3218 -+ int remaining_children_to_start;
3219 -+ apr_status_t rv;
3220 -+
3221 -+ ap_log_pid(pconf, ap_pid_fname);
3222 -+
3223 -+ first_server_limit = server_limit;
3224 -+ if (changed_limit_at_restart) {
3225 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
3226 -+ "WARNING: Attempt to change ServerLimit "
3227 -+ "ignored during restart");
3228 -+ changed_limit_at_restart = 0;
3229 -+ }
3230 -+
3231 -+ /* Initialize cross-process accept lock */
3232 -+ ap_lock_fname = apr_psprintf(_pconf, "%s.%" APR_PID_T_FMT,
3233 -+ ap_server_root_relative(_pconf, ap_lock_fname),
3234 -+ ap_my_pid);
3235 -+
3236 -+ rv = apr_proc_mutex_create(&accept_mutex, ap_lock_fname,
3237 -+ ap_accept_lock_mech, _pconf);
3238 -+ if (rv != APR_SUCCESS) {
3239 -+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
3240 -+ "Couldn't create accept lock (%s) (%d)",
3241 -+ ap_lock_fname, ap_accept_lock_mech);
3242 -+ mpm_state = AP_MPMQ_STOPPING;
3243 -+ return 1;
3244 -+ }
3245 -+
3246 -+#if APR_USE_SYSVSEM_SERIALIZE
3247 -+ if (ap_accept_lock_mech == APR_LOCK_DEFAULT ||
3248 -+ ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
3249 -+#else
3250 -+ if (ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
3251 -+#endif
3252 -+ rv = unixd_set_proc_mutex_perms(accept_mutex);
3253 -+ if (rv != APR_SUCCESS) {
3254 -+ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
3255 -+ "Couldn't set permissions on cross-process lock; "
3256 -+ "check User and Group directives");
3257 -+ mpm_state = AP_MPMQ_STOPPING;
3258 -+ return 1;
3259 -+ }
3260 -+ }
3261 -+
3262 -+ if (!is_graceful) {
3263 -+ if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
3264 -+ mpm_state = AP_MPMQ_STOPPING;
3265 -+ return 1;
3266 -+ }
3267 -+ /* fix the generation number in the global score; we just got a new,
3268 -+ * cleared scoreboard
3269 -+ */
3270 -+ ap_scoreboard_image->global->running_generation = ap_my_generation;
3271 -+ }
3272 -+
3273 -+ set_signals();
3274 -+
3275 -+ if (one_process) {
3276 -+ AP_MONCONTROL(1);
3277 -+ make_child(ap_server_conf, 0);
3278 -+ }
3279 -+ else {
3280 -+ if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
3281 -+ ap_daemons_max_free = ap_daemons_min_free + 1;
3282 -+
3283 -+ /* If we're doing a graceful_restart then we're going to see a lot
3284 -+ * of children exiting immediately when we get into the main loop
3285 -+ * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
3286 -+ * rapidly... and for each one that exits we'll start a new one until
3287 -+ * we reach at least daemons_min_free. But we may be permitted to
3288 -+ * start more than that, so we'll just keep track of how many we're
3289 -+ * supposed to start up without the 1 second penalty between each fork.
3290 -+ */
3291 -+ remaining_children_to_start = ap_daemons_to_start;
3292 -+ if (remaining_children_to_start > ap_daemons_limit) {
3293 -+ remaining_children_to_start = ap_daemons_limit;
3294 -+ }
3295 -+ if (!is_graceful) {
3296 -+ startup_children(remaining_children_to_start);
3297 -+ remaining_children_to_start = 0;
3298 -+ }
3299 -+ else {
3300 -+ /* give the system some time to recover before kicking into
3301 -+ * exponential mode
3302 -+ */
3303 -+ hold_off_on_exponential_spawning = 10;
3304 -+ }
3305 -+
3306 -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
3307 -+ "%s configured -- resuming normal operations",
3308 -+ ap_get_server_description());
3309 -+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
3310 -+ "Server built: %s", ap_get_server_built());
3311 -+#ifdef AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
3312 -+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
3313 -+ "AcceptMutex: %s (default: %s)",
3314 -+ apr_proc_mutex_name(accept_mutex),
3315 -+ apr_proc_mutex_defname());
3316 -+#endif
3317 -+ restart_pending = shutdown_pending = 0;
3318 -+
3319 -+ mpm_state = AP_MPMQ_RUNNING;
3320 -+
3321 -+ while (!restart_pending && !shutdown_pending) {
3322 -+ int child_slot;
3323 -+ apr_exit_why_e exitwhy;
3324 -+ int status, processed_status;
3325 -+ /* this is a memory leak, but I'll fix it later. */
3326 -+ apr_proc_t pid;
3327 -+
3328 -+ ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
3329 -+
3330 -+ /* XXX: if it takes longer than 1 second for all our children
3331 -+ * to start up and get into IDLE state then we may spawn an
3332 -+ * extra child
3333 -+ */
3334 -+ if (pid.pid != -1) {
3335 -+ processed_status = ap_process_child_status(&pid, exitwhy, status);
3336 -+ if (processed_status == APEXIT_CHILDFATAL) {
3337 -+ mpm_state = AP_MPMQ_STOPPING;
3338 -+ return 1;
3339 -+ }
3340 -+
3341 -+ /* non-fatal death... note that it's gone in the scoreboard. */
3342 -+ child_slot = find_child_by_pid(&pid);
3343 -+ if (child_slot >= 0) {
3344 -+ (void) ap_update_child_status_from_indexes(child_slot, 0, SERVER_DEAD,
3345 -+ (request_rec *) NULL);
3346 -+ if (processed_status == APEXIT_CHILDSICK) {
3347 -+ /* child detected a resource shortage (E[NM]FILE, ENOBUFS, etc)
3348 -+ * cut the fork rate to the minimum
3349 -+ */
3350 -+ idle_spawn_rate = 1;
3351 -+ }
3352 -+ else if (remaining_children_to_start
3353 -+ && child_slot < ap_daemons_limit) {
3354 -+ /* we're still doing a 1-for-1 replacement of dead
3355 -+ * children with new children
3356 -+ */
3357 -+ make_child(ap_server_conf, child_slot);
3358 -+ --remaining_children_to_start;
3359 -+ }
3360 -+#if APR_HAS_OTHER_CHILD
3361 -+ }
3362 -+ else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH, status) == APR_SUCCESS) {
3363 -+ /* handled */
3364 -+#endif
3365 -+ }
3366 -+ else if (is_graceful) {
3367 -+ /* Great, we've probably just lost a slot in the
3368 -+ * scoreboard. Somehow we don't know about this
3369 -+ * child.
3370 -+ */
3371 -+ ap_log_error(APLOG_MARK, APLOG_WARNING,
3372 -+ 0, ap_server_conf,
3373 -+ "long lost child came home! (pid %ld)", (long)pid.pid);
3374 -+ }
3375 -+ /* Don't perform idle maintenance when a child dies,
3376 -+ * only do it when there's a timeout. Remember only a
3377 -+ * finite number of children can die, and it's pretty
3378 -+ * pathological for a lot to die suddenly.
3379 -+ */
3380 -+ continue;
3381 -+ }
3382 -+ else if (remaining_children_to_start) {
3383 -+ /* we hit a 1 second timeout in which none of the previous
3384 -+ * generation of children needed to be reaped... so assume
3385 -+ * they're all done, and pick up the slack if any is left.
3386 -+ */
3387 -+ startup_children(remaining_children_to_start);
3388 -+ remaining_children_to_start = 0;
3389 -+ /* In any event we really shouldn't do the code below because
3390 -+ * few of the servers we just started are in the IDLE state
3391 -+ * yet, so we'd mistakenly create an extra server.
3392 -+ */
3393 -+ continue;
3394 -+ }
3395 -+
3396 -+ perform_idle_server_maintenance(pconf);
3397 -+#ifdef TPF
3398 -+ shutdown_pending = os_check_server(tpf_server_name);
3399 -+ ap_check_signals();
3400 -+ sleep(1);
3401 -+#endif /*TPF */
3402 -+ }
3403 -+ } /* one_process */
3404 -+
3405 -+ mpm_state = AP_MPMQ_STOPPING;
3406 -+
3407 -+ if (shutdown_pending && !is_graceful) {
3408 -+ /* Time to shut down:
3409 -+ * Kill child processes, tell them to call child_exit, etc...
3410 -+ */
3411 -+ if (unixd_killpg(getpgrp(), SIGTERM) < 0) {
3412 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGTERM");
3413 -+ }
3414 -+ ap_reclaim_child_processes(1); /* Start with SIGTERM */
3415 -+
3416 -+ /* cleanup pid file on normal shutdown */
3417 -+ {
3418 -+ const char *pidfile = NULL;
3419 -+ pidfile = ap_server_root_relative (pconf, ap_pid_fname);
3420 -+ if ( pidfile != NULL && unlink(pidfile) == 0)
3421 -+ ap_log_error(APLOG_MARK, APLOG_INFO,
3422 -+ 0, ap_server_conf,
3423 -+ "removed PID file %s (pid=%ld)",
3424 -+ pidfile, (long)getpid());
3425 -+ }
3426 -+
3427 -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
3428 -+ "caught SIGTERM, shutting down");
3429 -+
3430 -+ return 1;
3431 -+ } else if (shutdown_pending) {
3432 -+ /* Time to perform a graceful shut down:
3433 -+ * Reap the inactive children, and ask the active ones
3434 -+ * to close their listeners, then wait until they are
3435 -+ * all done to exit.
3436 -+ */
3437 -+ int active_children;
3438 -+ apr_time_t cutoff = 0;
3439 -+
3440 -+ /* Stop listening */
3441 -+ ap_close_listeners();
3442 -+
3443 -+ /* kill off the idle ones */
3444 -+ ap_mpm_pod_killpg(pod, ap_max_daemons_limit);
3445 -+
3446 -+ /* Send SIGUSR1 to the active children */
3447 -+ active_children = 0;
3448 -+ for (index = 0; index < ap_daemons_limit; ++index) {
3449 -+ if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
3450 -+ /* Ask each child to close its listeners. */
3451 -+ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
3452 -+ active_children++;
3453 -+ }
3454 -+ }
3455 -+
3456 -+ /* Allow each child which actually finished to exit */
3457 -+ ap_relieve_child_processes();
3458 -+
3459 -+ /* cleanup pid file */
3460 -+ {
3461 -+ const char *pidfile = NULL;
3462 -+ pidfile = ap_server_root_relative (pconf, ap_pid_fname);
3463 -+ if ( pidfile != NULL && unlink(pidfile) == 0)
3464 -+ ap_log_error(APLOG_MARK, APLOG_INFO,
3465 -+ 0, ap_server_conf,
3466 -+ "removed PID file %s (pid=%ld)",
3467 -+ pidfile, (long)getpid());
3468 -+ }
3469 -+
3470 -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
3471 -+ "caught " AP_SIG_GRACEFUL_STOP_STRING ", shutting down gracefully");
3472 -+
3473 -+ if (ap_graceful_shutdown_timeout) {
3474 -+ cutoff = apr_time_now() +
3475 -+ apr_time_from_sec(ap_graceful_shutdown_timeout);
3476 -+ }
3477 -+
3478 -+ /* Don't really exit until each child has finished */
3479 -+ shutdown_pending = 0;
3480 -+ do {
3481 -+ /* Pause for a second */
3482 -+ sleep(1);
3483 -+
3484 -+ /* Relieve any children which have now exited */
3485 -+ ap_relieve_child_processes();
3486 -+
3487 -+ active_children = 0;
3488 -+ for (index = 0; index < ap_daemons_limit; ++index) {
3489 -+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
3490 -+ active_children = 1;
3491 -+ /* Having just one child is enough to stay around */
3492 -+ break;
3493 -+ }
3494 -+ }
3495 -+ } while (!shutdown_pending && active_children &&
3496 -+ (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
3497 -+
3498 -+ /* We might be here because we received SIGTERM, either
3499 -+ * way, try and make sure that all of our processes are
3500 -+ * really dead.
3501 -+ */
3502 -+ unixd_killpg(getpgrp(), SIGTERM);
3503 -+
3504 -+ return 1;
3505 -+ }
3506 -+
3507 -+ /* we've been told to restart */
3508 -+ apr_signal(SIGHUP, SIG_IGN);
3509 -+ apr_signal(AP_SIG_GRACEFUL, SIG_IGN);
3510 -+ if (one_process) {
3511 -+ /* not worth thinking about */
3512 -+ return 1;
3513 -+ }
3514 -+
3515 -+ /* advance to the next generation */
3516 -+ /* XXX: we really need to make sure this new generation number isn't in
3517 -+ * use by any of the children.
3518 -+ */
3519 -+ ++ap_my_generation;
3520 -+ ap_scoreboard_image->global->running_generation = ap_my_generation;
3521 -+
3522 -+ if (is_graceful) {
3523 -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
3524 -+ "Graceful restart requested, doing restart");
3525 -+
3526 -+ /* kill off the idle ones */
3527 -+ ap_mpm_pod_killpg(pod, ap_max_daemons_limit);
3528 -+
3529 -+ /* This is mostly for debugging... so that we know what is still
3530 -+ * gracefully dealing with existing request. This will break
3531 -+ * in a very nasty way if we ever have the scoreboard totally
3532 -+ * file-based (no shared memory)
3533 -+ */
3534 -+ for (index = 0; index < ap_daemons_limit; ++index) {
3535 -+ if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
3536 -+ ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL;
3537 -+ /* Ask each child to close its listeners.
3538 -+ *
3539 -+ * NOTE: we use the scoreboard, because if we send SIGUSR1
3540 -+ * to every process in the group, this may include CGI's,
3541 -+ * piped loggers, etc. They almost certainly won't handle
3542 -+ * it gracefully.
3543 -+ */
3544 -+ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
3545 -+ }
3546 -+ }
3547 -+ }
3548 -+ else {
3549 -+ /* Kill 'em off */
3550 -+ if (unixd_killpg(getpgrp(), SIGHUP) < 0) {
3551 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "killpg SIGHUP");
3552 -+ }
3553 -+ ap_reclaim_child_processes(0); /* Not when just starting up */
3554 -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
3555 -+ "SIGHUP received. Attempting to restart");
3556 -+ }
3557 -+
3558 -+ return 0;
3559 -+}
3560 -+
3561 -+/* This really should be a post_config hook, but the error log is already
3562 -+ * redirected by that point, so we need to do this in the open_logs phase.
3563 -+ */
3564 -+static int itk_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
3565 -+{
3566 -+ apr_status_t rv;
3567 -+
3568 -+ pconf = p;
3569 -+ ap_server_conf = s;
3570 -+
3571 -+ if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
3572 -+ ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0,
3573 -+ NULL, "no listening sockets available, shutting down");
3574 -+ return DONE;
3575 -+ }
3576 -+
3577 -+ if ((rv = ap_mpm_pod_open(pconf, &pod))) {
3578 -+ ap_log_error(APLOG_MARK, APLOG_CRIT|APLOG_STARTUP, rv, NULL,
3579 -+ "Could not open pipe-of-death.");
3580 -+ return DONE;
3581 -+ }
3582 -+ return OK;
3583 -+}
3584 -+
3585 -+static int itk_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
3586 -+{
3587 -+ static int restart_num = 0;
3588 -+ int no_detach, debug, foreground;
3589 -+ apr_status_t rv;
3590 -+
3591 -+ mpm_state = AP_MPMQ_STARTING;
3592 -+
3593 -+ debug = ap_exists_config_define("DEBUG");
3594 -+
3595 -+ if (debug) {
3596 -+ foreground = one_process = 1;
3597 -+ no_detach = 0;
3598 -+ }
3599 -+ else
3600 -+ {
3601 -+ no_detach = ap_exists_config_define("NO_DETACH");
3602 -+ one_process = ap_exists_config_define("ONE_PROCESS");
3603 -+ foreground = ap_exists_config_define("FOREGROUND");
3604 -+ }
3605 -+
3606 -+ /* sigh, want this only the second time around */
3607 -+ if (restart_num++ == 1) {
3608 -+ is_graceful = 0;
3609 -+
3610 -+ if (!one_process && !foreground) {
3611 -+ rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
3612 -+ : APR_PROC_DETACH_DAEMONIZE);
3613 -+ if (rv != APR_SUCCESS) {
3614 -+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
3615 -+ "apr_proc_detach failed");
3616 -+ return HTTP_INTERNAL_SERVER_ERROR;
3617 -+ }
3618 -+ }
3619 -+
3620 -+ parent_pid = ap_my_pid = getpid();
3621 -+ }
3622 -+
3623 -+ unixd_pre_config(ptemp);
3624 -+ ap_listen_pre_config();
3625 -+ ap_daemons_to_start = DEFAULT_START_DAEMON;
3626 -+ ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
3627 -+ ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
3628 -+ ap_daemons_limit = server_limit;
3629 -+ ap_pid_fname = DEFAULT_PIDLOG;
3630 -+ ap_lock_fname = DEFAULT_LOCKFILE;
3631 -+ ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
3632 -+ ap_extended_status = 0;
3633 -+#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
3634 -+ ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
3635 -+#endif
3636 -+
3637 -+ apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
3638 -+
3639 -+ return OK;
3640 -+}
3641 -+
3642 -+static int itk_post_perdir_config(request_rec *r)
3643 -+{
3644 -+ uid_t wanted_uid;
3645 -+ gid_t wanted_gid;
3646 -+ const char *wanted_username;
3647 -+ int err = 0;
3648 -+
3649 -+ itk_server_conf *sconf =
3650 -+ (itk_server_conf *) ap_get_module_config(r->server->module_config, &mpm_itk_module);
3651 -+
3652 -+ /* Enforce MaxClientsVhost. */
3653 -+ if (sconf->max_clients_vhost > 0) {
3654 -+ int i, num_other_servers = 0;
3655 -+ for (i = 0; i < ap_daemons_limit; ++i) {
3656 -+ worker_score *ws = &ap_scoreboard_image->servers[i][0];
3657 -+ if (ws->status >= SERVER_BUSY_READ && strncmp(ws->vhost, r->server->server_hostname, 31) == 0)
3658 -+ ++num_other_servers;
3659 -+ }
3660 -+
3661 -+ if (num_other_servers > sconf->max_clients_vhost) {
3662 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \
3663 -+ "MaxClientsVhost reached for %s, refusing client.",
3664 -+ r->server->server_hostname);
3665 -+ return HTTP_SERVICE_UNAVAILABLE;
3666 -+ }
3667 -+ }
3668 -+
3669 -+ itk_per_dir_conf *dconf =
3670 -+ (itk_per_dir_conf *) ap_get_module_config(r->per_dir_config, &mpm_itk_module);
3671 -+
3672 -+ strncpy(ap_scoreboard_image->servers[my_child_num][0].vhost, r->server->server_hostname, 31);
3673 -+ ap_scoreboard_image->servers[my_child_num][0].vhost[31] = 0;
3674 -+
3675 -+ if (dconf->nice_value != UNSET_NICE_VALUE &&
3676 -+ setpriority(PRIO_PROCESS, 0, dconf->nice_value)) {
3677 -+ _DBG("setpriority(): %s", strerror(errno));
3678 -+ err = 1;
3679 -+ }
3680 -+
3681 -+ wanted_uid = dconf->uid;
3682 -+ wanted_gid = dconf->gid;
3683 -+ wanted_username = dconf->username;
3684 -+
3685 -+ if (wanted_uid == -1 || wanted_gid == -1) {
3686 -+ wanted_uid = unixd_config.user_id;
3687 -+ wanted_gid = unixd_config.group_id;
3688 -+ wanted_username = unixd_config.user_name;
3689 -+ }
3690 -+
3691 -+ if (!err && wanted_uid != -1 && wanted_gid != -1 && (getuid() != wanted_uid || getgid() != wanted_gid)) {
3692 -+ if (setgid(wanted_gid)) {
3693 -+ _DBG("setgid(%d): %s", wanted_gid, strerror(errno));
3694 -+ err = 1;
3695 -+ } else if (initgroups(wanted_username, wanted_gid)) {
3696 -+ _DBG("initgroups(%s, %d): %s", wanted_username, wanted_gid, strerror(errno));
3697 -+ err = 1;
3698 -+ } else if (setuid(wanted_uid)) {
3699 -+ _DBG("setuid(%d): %s", wanted_uid, strerror(errno));
3700 -+ err = 1;
3701 -+ }
3702 -+ }
3703 -+
3704 -+ /*
3705 -+ * Most likely a case of switching uid/gid within a persistent
3706 -+ * connection; the RFCs allow us to just close the connection
3707 -+ * at anytime, so we excercise our right. :-)
3708 -+ */
3709 -+ if (err) {
3710 -+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \
3711 -+ "Couldn't set uid/gid/priority, closing connection.");
3712 -+ ap_lingering_close(r->connection);
3713 -+ exit(0);
3714 -+ }
3715 -+ return OK;
3716 -+}
3717 -+
3718 -+static void itk_hooks(apr_pool_t *p)
3719 -+{
3720 -+ /* The itk open_logs phase must run before the core's, or stderr
3721 -+ * will be redirected to a file, and the messages won't print to the
3722 -+ * console.
3723 -+ */
3724 -+ static const char *const aszSucc[] = {"core.c", NULL};
3725 -+
3726 -+#ifdef AUX3
3727 -+ (void) set42sig();
3728 -+#endif
3729 -+
3730 -+ ap_hook_open_logs(itk_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
3731 -+ /* we need to set the MPM state before other pre-config hooks use MPM query
3732 -+ * to retrieve it, so register as REALLY_FIRST
3733 -+ */
3734 -+ ap_hook_pre_config(itk_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
3735 -+
3736 -+ /* set the uid as fast as possible, but not before merging per-dit config */
3737 -+ ap_hook_header_parser(itk_post_perdir_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
3738 -+}
3739 -+
3740 -+static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
3741 -+{
3742 -+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3743 -+ if (err != NULL) {
3744 -+ return err;
3745 -+ }
3746 -+
3747 -+ ap_daemons_to_start = atoi(arg);
3748 -+ return NULL;
3749 -+}
3750 -+
3751 -+static const char *set_min_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
3752 -+{
3753 -+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3754 -+ if (err != NULL) {
3755 -+ return err;
3756 -+ }
3757 -+
3758 -+ ap_daemons_min_free = atoi(arg);
3759 -+ if (ap_daemons_min_free <= 0) {
3760 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3761 -+ "WARNING: detected MinSpareServers set to non-positive.");
3762 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3763 -+ "Resetting to 1 to avoid almost certain Apache failure.");
3764 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3765 -+ "Please read the documentation.");
3766 -+ ap_daemons_min_free = 1;
3767 -+ }
3768 -+
3769 -+ return NULL;
3770 -+}
3771 -+
3772 -+static const char *set_max_free_servers(cmd_parms *cmd, void *dummy, const char *arg)
3773 -+{
3774 -+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3775 -+ if (err != NULL) {
3776 -+ return err;
3777 -+ }
3778 -+
3779 -+ ap_daemons_max_free = atoi(arg);
3780 -+ return NULL;
3781 -+}
3782 -+
3783 -+static const char *set_max_clients (cmd_parms *cmd, void *dummy, const char *arg)
3784 -+{
3785 -+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3786 -+ if (err != NULL) {
3787 -+ return err;
3788 -+ }
3789 -+
3790 -+ ap_daemons_limit = atoi(arg);
3791 -+ if (ap_daemons_limit > server_limit) {
3792 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3793 -+ "WARNING: MaxClients of %d exceeds ServerLimit value "
3794 -+ "of %d servers,", ap_daemons_limit, server_limit);
3795 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3796 -+ " lowering MaxClients to %d. To increase, please "
3797 -+ "see the ServerLimit", server_limit);
3798 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3799 -+ " directive.");
3800 -+ ap_daemons_limit = server_limit;
3801 -+ }
3802 -+ else if (ap_daemons_limit < 1) {
3803 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3804 -+ "WARNING: Require MaxClients > 0, setting to 1");
3805 -+ ap_daemons_limit = 1;
3806 -+ }
3807 -+ return NULL;
3808 -+}
3809 -+
3810 -+static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
3811 -+{
3812 -+ int tmp_server_limit;
3813 -+
3814 -+ const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3815 -+ if (err != NULL) {
3816 -+ return err;
3817 -+ }
3818 -+
3819 -+ tmp_server_limit = atoi(arg);
3820 -+ /* you cannot change ServerLimit across a restart; ignore
3821 -+ * any such attempts
3822 -+ */
3823 -+ if (first_server_limit &&
3824 -+ tmp_server_limit != server_limit) {
3825 -+ /* how do we log a message? the error log is a bit bucket at this
3826 -+ * point; we'll just have to set a flag so that ap_mpm_run()
3827 -+ * logs a warning later
3828 -+ */
3829 -+ changed_limit_at_restart = 1;
3830 -+ return NULL;
3831 -+ }
3832 -+ server_limit = tmp_server_limit;
3833 -+
3834 -+ if (server_limit > MAX_SERVER_LIMIT) {
3835 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3836 -+ "WARNING: ServerLimit of %d exceeds compile time limit "
3837 -+ "of %d servers,", server_limit, MAX_SERVER_LIMIT);
3838 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3839 -+ " lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
3840 -+ server_limit = MAX_SERVER_LIMIT;
3841 -+ }
3842 -+ else if (server_limit < 1) {
3843 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3844 -+ "WARNING: Require ServerLimit > 0, setting to 1");
3845 -+ server_limit = 1;
3846 -+ }
3847 -+ return NULL;
3848 -+}
3849 -+
3850 -+static const char *assign_user_id (cmd_parms *cmd, void *ptr, const char *user_name, const char *group_name)
3851 -+{
3852 -+ itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr;
3853 -+ dconf->username = apr_pstrdup(cmd->pool, user_name);
3854 -+ dconf->uid = ap_uname2id(user_name);
3855 -+ dconf->gid = ap_gname2id(group_name);
3856 -+ return NULL;
3857 -+}
3858 -+
3859 -+static const char *set_max_clients_vhost (cmd_parms *cmd, void *dummy, const char *arg)
3860 -+{
3861 -+ itk_server_conf *sconf =
3862 -+ (itk_server_conf *) ap_get_module_config(cmd->server->module_config, &mpm_itk_module);
3863 -+ sconf->max_clients_vhost = atoi(arg);
3864 -+ return NULL;
3865 -+}
3866 -+
3867 -+static const char *set_nice_value (cmd_parms *cmd, void *ptr, const char *arg)
3868 -+{
3869 -+ itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr;
3870 -+ int nice_value = atoi(arg);
3871 -+
3872 -+ if (nice_value < -20) {
3873 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3874 -+ "WARNING: NiceValue of %d is below -20, increasing NiceValue to -20.",
3875 -+ nice_value);
3876 -+ nice_value = -20;
3877 -+ }
3878 -+ else if (nice_value > 19) {
3879 -+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
3880 -+ "WARNING: NiceValue of %d is above 19, lowering NiceValue to 19.",
3881 -+ nice_value);
3882 -+ nice_value = 19;
3883 -+ }
3884 -+ dconf->nice_value = nice_value;
3885 -+ return NULL;
3886 -+}
3887 -+
3888 -+static const command_rec itk_cmds[] = {
3889 -+UNIX_DAEMON_COMMANDS,
3890 -+LISTEN_COMMANDS,
3891 -+AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
3892 -+ "Number of child processes launched at server startup"),
3893 -+AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
3894 -+ "Minimum number of idle children, to handle request spikes"),
3895 -+AP_INIT_TAKE1("MaxSpareServers", set_max_free_servers, NULL, RSRC_CONF,
3896 -+ "Maximum number of idle children"),
3897 -+AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
3898 -+ "Maximum number of children alive at the same time"),
3899 -+AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
3900 -+ "Maximum value of MaxClients for this run of Apache"),
3901 -+AP_INIT_TAKE2("AssignUserID", assign_user_id, NULL, RSRC_CONF|ACCESS_CONF,
3902 -+ "Tie a virtual host to a specific child process."),
3903 -+AP_INIT_TAKE1("MaxClientsVHost", set_max_clients_vhost, NULL, RSRC_CONF,
3904 -+ "Maximum number of children alive at the same time for this virtual host."),
3905 -+AP_INIT_TAKE1("NiceValue", set_nice_value, NULL, RSRC_CONF|ACCESS_CONF,
3906 -+ "Set nice value for the given vhost, from -20 (highest priority) to 19 (lowest priority)."),
3907 -+AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
3908 -+{ NULL }
3909 -+};
3910 -+
3911 -+/* == allocate a private per-dir config structure == */
3912 -+static void *itk_create_dir_config(apr_pool_t *p, char *dummy)
3913 -+{
3914 -+ itk_per_dir_conf *c = (itk_per_dir_conf *)
3915 -+ apr_pcalloc(p, sizeof(itk_per_dir_conf));
3916 -+ c->uid = c->gid = -1;
3917 -+ c->nice_value = UNSET_NICE_VALUE;
3918 -+ return c;
3919 -+}
3920 -+
3921 -+/* == merge the parent per-dir config structure into ours == */
3922 -+static void *itk_merge_dir_config(apr_pool_t *p, void *parent_ptr, void *child_ptr)
3923 -+{
3924 -+ itk_per_dir_conf *c = (itk_per_dir_conf *)
3925 -+ apr_pcalloc(p, sizeof(itk_per_dir_conf));
3926 -+ itk_per_dir_conf *parent = (itk_per_dir_conf *) parent_ptr;
3927 -+ itk_per_dir_conf *child = (itk_per_dir_conf *) child_ptr;
3928 -+
3929 -+ if (child->username != NULL) {
3930 -+ c->username = apr_pstrdup(p, child->username);
3931 -+ c->uid = child->uid;
3932 -+ c->gid = child->gid;
3933 -+ } else if (parent->username != NULL) {
3934 -+ c->username = apr_pstrdup(p, parent->username);
3935 -+ c->uid = parent->uid;
3936 -+ c->gid = parent->gid;
3937 -+ }
3938 -+ if (child->nice_value != UNSET_NICE_VALUE) {
3939 -+ c->nice_value = child->nice_value;
3940 -+ } else {
3941 -+ c->nice_value = parent->nice_value;
3942 -+ }
3943 -+ return c;
3944 -+}
3945 -+
3946 -+/* == allocate a private server config structure == */
3947 -+static void *itk_create_server_config(apr_pool_t *p, server_rec *s)
3948 -+{
3949 -+ itk_server_conf *c = (itk_server_conf *)
3950 -+ apr_pcalloc(p, sizeof(itk_server_conf));
3951 -+ c->max_clients_vhost = -1;
3952 -+ return c;
3953 -+}
3954 -+
3955 -+module AP_MODULE_DECLARE_DATA mpm_itk_module = {
3956 -+ MPM20_MODULE_STUFF,
3957 -+ ap_mpm_rewrite_args, /* hook to run before apache parses args */
3958 -+ itk_create_dir_config, /* create per-directory config structure */
3959 -+ itk_merge_dir_config, /* merge per-directory config structures */
3960 -+ itk_create_server_config, /* create per-server config structure */
3961 -+ NULL, /* merge per-server config structures */
3962 -+ itk_cmds, /* command apr_table_t */
3963 -+ itk_hooks, /* register hooks */
3964 -+};
3965 -Index: httpd-2.2.11/server/mpm/experimental/itk/mpm.h
3966 -===================================================================
3967 ---- /dev/null
3968 -+++ httpd-2.2.11/server/mpm/experimental/itk/mpm.h
3969 -@@ -0,0 +1,68 @@
3970 -+/* Licensed to the Apache Software Foundation (ASF) under one or more
3971 -+ * contributor license agreements. See the NOTICE file distributed with
3972 -+ * this work for additional information regarding copyright ownership.
3973 -+ * The ASF licenses this file to You under the Apache License, Version 2.0
3974 -+ * (the "License"); you may not use this file except in compliance with
3975 -+ * the License. You may obtain a copy of the License at
3976 -+ *
3977 -+ * http://www.apache.org/licenses/LICENSE-2.0
3978 -+ *
3979 -+ * Unless required by applicable law or agreed to in writing, software
3980 -+ * distributed under the License is distributed on an "AS IS" BASIS,
3981 -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3982 -+ * See the License for the specific language governing permissions and
3983 -+ * limitations under the License.
3984 -+ *
3985 -+ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
3986 -+ * Licensed under the same terms as the rest of Apache.
3987 -+ *
3988 -+ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
3989 -+ * Licensed under the same terms as the rest of Apache.
3990 -+ */
3991 -+
3992 -+/**
3993 -+ * @file itk/mpm.h
3994 -+ * @brief ITK MPM (setuid per-vhost, no threads)
3995 -+ *
3996 -+ * @defgroup APACHE_MPM_ITK Apache ITK
3997 -+ * @ingroup APACHE_MPM APACHE_OS_UNIX
3998 -+ * @{
3999 -+ */
4000 -+
4001 -+#include "httpd.h"
4002 -+#include "mpm_default.h"
4003 -+#include "scoreboard.h"
4004 -+#include "unixd.h"
4005 -+
4006 -+#ifndef APACHE_MPM_ITK_H
4007 -+#define APACHE_MPM_ITK_H
4008 -+
4009 -+#define ITK_MPM
4010 -+
4011 -+#define MPM_NAME "ITK"
4012 -+
4013 -+#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
4014 -+#define AP_MPM_WANT_WAIT_OR_TIMEOUT
4015 -+#define AP_MPM_WANT_PROCESS_CHILD_STATUS
4016 -+#define AP_MPM_WANT_SET_PIDFILE
4017 -+#define AP_MPM_WANT_SET_SCOREBOARD
4018 -+#define AP_MPM_WANT_SET_LOCKFILE
4019 -+#define AP_MPM_WANT_SET_MAX_REQUESTS
4020 -+#define AP_MPM_WANT_SET_COREDUMPDIR
4021 -+#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
4022 -+#define AP_MPM_WANT_SIGNAL_SERVER
4023 -+#define AP_MPM_WANT_SET_MAX_MEM_FREE
4024 -+#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER
4025 -+#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN
4026 -+#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
4027 -+
4028 -+#define AP_MPM_USES_POD 1
4029 -+#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
4030 -+#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
4031 -+#define MPM_ACCEPT_FUNC unixd_accept
4032 -+
4033 -+extern int ap_threads_per_child;
4034 -+extern int ap_max_daemons_limit;
4035 -+extern server_rec *ap_server_conf;
4036 -+#endif /* APACHE_MPM_ITK_H */
4037 -+/** @} */
4038 -Index: httpd-2.2.11/server/mpm/experimental/itk/mpm_default.h
4039 -===================================================================
4040 ---- /dev/null
4041 -+++ httpd-2.2.11/server/mpm/experimental/itk/mpm_default.h
4042 -@@ -0,0 +1,80 @@
4043 -+/* Licensed to the Apache Software Foundation (ASF) under one or more
4044 -+ * contributor license agreements. See the NOTICE file distributed with
4045 -+ * this work for additional information regarding copyright ownership.
4046 -+ * The ASF licenses this file to You under the Apache License, Version 2.0
4047 -+ * (the "License"); you may not use this file except in compliance with
4048 -+ * the License. You may obtain a copy of the License at
4049 -+ *
4050 -+ * http://www.apache.org/licenses/LICENSE-2.0
4051 -+ *
4052 -+ * Unless required by applicable law or agreed to in writing, software
4053 -+ * distributed under the License is distributed on an "AS IS" BASIS,
4054 -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4055 -+ * See the License for the specific language governing permissions and
4056 -+ * limitations under the License.
4057 -+ *
4058 -+ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
4059 -+ * Licensed under the same terms as the rest of Apache.
4060 -+ *
4061 -+ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
4062 -+ * Licensed under the same terms as the rest of Apache.
4063 -+ */
4064 -+
4065 -+/**
4066 -+ * @file itk/mpm_default.h
4067 -+ * @brief ITK MPM defaults
4068 -+ *
4069 -+ * @addtogroup APACHE_MPM_ITK
4070 -+ * @{
4071 -+ */
4072 -+
4073 -+#ifndef APACHE_MPM_DEFAULT_H
4074 -+#define APACHE_MPM_DEFAULT_H
4075 -+
4076 -+/* Number of servers to spawn off by default --- also, if fewer than
4077 -+ * this free when the caretaker checks, it will spawn more.
4078 -+ */
4079 -+#ifndef DEFAULT_START_DAEMON
4080 -+#define DEFAULT_START_DAEMON 5
4081 -+#endif
4082 -+
4083 -+/* Maximum number of *free* server processes --- more than this, and
4084 -+ * they will die off.
4085 -+ */
4086 -+
4087 -+#ifndef DEFAULT_MAX_FREE_DAEMON
4088 -+#define DEFAULT_MAX_FREE_DAEMON 10
4089 -+#endif
4090 -+
4091 -+/* Minimum --- fewer than this, and more will be created */
4092 -+
4093 -+#ifndef DEFAULT_MIN_FREE_DAEMON
4094 -+#define DEFAULT_MIN_FREE_DAEMON 5
4095 -+#endif
4096 -+
4097 -+/* File used for accept locking, when we use a file */
4098 -+#ifndef DEFAULT_LOCKFILE
4099 -+#define DEFAULT_LOCKFILE DEFAULT_REL_RUNTIMEDIR "/accept.lock"
4100 -+#endif
4101 -+
4102 -+/* Where the main/parent process's pid is logged */
4103 -+#ifndef DEFAULT_PIDLOG
4104 -+#define DEFAULT_PIDLOG DEFAULT_REL_RUNTIMEDIR "/httpd.pid"
4105 -+#endif
4106 -+
4107 -+/*
4108 -+ * Interval, in microseconds, between scoreboard maintenance.
4109 -+ */
4110 -+#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
4111 -+#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
4112 -+#endif
4113 -+
4114 -+/* Number of requests to try to handle in a single process. If <= 0,
4115 -+ * the children don't die off.
4116 -+ */
4117 -+#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
4118 -+#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
4119 -+#endif
4120 -+
4121 -+#endif /* AP_MPM_DEFAULT_H */
4122 -+/** @} */
4123 -Index: httpd-2.2.11/server/mpm/config.m4
4124 -===================================================================
4125 ---- httpd-2.2.11.orig/server/mpm/config.m4
4126 -+++ httpd-2.2.11/server/mpm/config.m4
4127 -@@ -1,7 +1,7 @@
4128 - AC_MSG_CHECKING(which MPM to use)
4129 - AC_ARG_WITH(mpm,
4130 - APACHE_HELP_STRING(--with-mpm=MPM,Choose the process model for Apache to use.
4131 -- MPM={beos|event|worker|prefork|mpmt_os2|peruser}),[
4132 -+ MPM={beos|event|worker|prefork|mpmt_os2|peruser|itk}),[
4133 - APACHE_MPM=$withval
4134 - ],[
4135 - if test "x$APACHE_MPM" = "x"; then
4136 -@@ -23,7 +23,7 @@ ap_mpm_is_threaded ()
4137 -
4138 - ap_mpm_is_experimental ()
4139 - {
4140 -- if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "peruser" ; then
4141 -+ if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "peruser" -o "$apache_cv_mpm" = "itk" ; then
4142 - return 0
4143 - else
4144 - return 1
4145 -@@ -66,6 +66,11 @@ if ap_mpm_is_experimental; then
4146 - else
4147 - MPM_SUBDIR_NAME=$MPM_NAME
4148 - fi
4149 -+
4150 -+if test "$apache_cv_mpm" = "itk" ; then
4151 -+ AC_CHECK_LIB(cap, cap_init)
4152 -+fi
4153 -+
4154 - MPM_DIR=server/mpm/$MPM_SUBDIR_NAME
4155 - MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la
4156 -
4157 -Index: httpd-2.2.11/include/http_request.h
4158 -===================================================================
4159 ---- httpd-2.2.11.orig/include/http_request.h
4160 -+++ httpd-2.2.11/include/http_request.h
4161 -@@ -12,6 +12,12 @@
4162 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4163 - * See the License for the specific language governing permissions and
4164 - * limitations under the License.
4165 -+ *
4166 -+ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
4167 -+ * Licensed under the same terms as the rest of Apache.
4168 -+ *
4169 -+ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
4170 -+ * Licensed under the same terms as the rest of Apache.
4171 - */
4172 -
4173 - /**
4174 -@@ -350,6 +356,15 @@ AP_DECLARE_HOOK(int,auth_checker,(reques
4175 - */
4176 - AP_DECLARE_HOOK(void,insert_filter,(request_rec *r))
4177 -
4178 -+/**
4179 -+ * This hook allows modules to affect the request immediately after the
4180 -+ * per-directory configuration for the request has been generated. This allows
4181 -+ * modules to make decisions based upon the current directory configuration
4182 -+ * @param r The current request
4183 -+ * @return OK or DECLINED
4184 -+ */
4185 -+AP_DECLARE_HOOK(int,post_perdir_config,(request_rec *r))
4186 -+
4187 - AP_DECLARE(int) ap_location_walk(request_rec *r);
4188 - AP_DECLARE(int) ap_directory_walk(request_rec *r);
4189 - AP_DECLARE(int) ap_file_walk(request_rec *r);
4190 -Index: httpd-2.2.11/server/request.c
4191 -===================================================================
4192 ---- httpd-2.2.11.orig/server/request.c
4193 -+++ httpd-2.2.11/server/request.c
4194 -@@ -12,6 +12,12 @@
4195 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4196 - * See the License for the specific language governing permissions and
4197 - * limitations under the License.
4198 -+ *
4199 -+ * Portions copyright 2005-2009 Steinar H. Gunderson <sgunderson@×××××××.com>.
4200 -+ * Licensed under the same terms as the rest of Apache.
4201 -+ *
4202 -+ * Portions copyright 2008 Knut Auvor Grythe <knut@×××××.no>.
4203 -+ * Licensed under the same terms as the rest of Apache.
4204 - */
4205 -
4206 - /*
4207 -@@ -61,6 +67,7 @@ APR_HOOK_STRUCT(
4208 - APR_HOOK_LINK(auth_checker)
4209 - APR_HOOK_LINK(insert_filter)
4210 - APR_HOOK_LINK(create_request)
4211 -+ APR_HOOK_LINK(post_perdir_config)
4212 - )
4213 -
4214 - AP_IMPLEMENT_HOOK_RUN_FIRST(int,translate_name,
4215 -@@ -80,6 +87,8 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(int,auth_che
4216 - AP_IMPLEMENT_HOOK_VOID(insert_filter, (request_rec *r), (r))
4217 - AP_IMPLEMENT_HOOK_RUN_ALL(int, create_request,
4218 - (request_rec *r), (r), OK, DECLINED)
4219 -+AP_IMPLEMENT_HOOK_RUN_ALL(int,post_perdir_config,
4220 -+ (request_rec *r), (r), OK, DECLINED)
4221 -
4222 -
4223 - static int decl_die(int status, char *phase, request_rec *r)
4224 -@@ -158,6 +167,13 @@ AP_DECLARE(int) ap_process_request_inter
4225 - return access_status;
4226 - }
4227 -
4228 -+ /* First chance to handle the request after per-directory configuration is
4229 -+ * generated
4230 -+ */
4231 -+ if ((access_status = ap_run_post_perdir_config(r))) {
4232 -+ return access_status;
4233 -+ }
4234 -+
4235 - /* Only on the main request! */
4236 - if (r->main == NULL) {
4237 - if ((access_status = ap_run_header_parser(r))) {