Gentoo Archives: gentoo-commits

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