~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to server/mpm/experimental/event/event.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
 
2
 * contributor license agreements.  See the NOTICE file distributed with
 
3
 * this work for additional information regarding copyright ownership.
 
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
5
 * (the "License"); you may not use this file except in compliance with
 
6
 * the License.  You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/**
 
18
 * This MPM tries to fix the 'keep alive problem' in HTTP.
 
19
 *
 
20
 * After a client completes the first request, the client can keep the
 
21
 * connection open to send more requests with the same socket.  This can save
 
22
 * signifigant overhead in creating TCP connections.  However, the major
 
23
 * disadvantage is that Apache traditionally keeps an entire child
 
24
 * process/thread waiting for data from the client.  To solve this problem,
 
25
 * this MPM has a dedicated thread for handling both the Listenting sockets,
 
26
 * and all sockets that are in a Keep Alive status.
 
27
 *
 
28
 * The MPM assumes the underlying apr_pollset implmentation is somewhat
 
29
 * threadsafe.  This currently is only compatible with KQueue and EPoll.  This
 
30
 * enables the MPM to avoid extra high level locking or having to wake up the
 
31
 * listener thread when a keep-alive socket needs to be sent to it.
 
32
 *
 
33
 * This MPM not preform well on older platforms that do not have very good
 
34
 * threading, like Linux with a 2.4 kernel, but this does not matter, since we
 
35
 * require EPoll or KQueue.
 
36
 *
 
37
 * For FreeBSD, use 5.3.  It is possible to run this MPM on FreeBSD 5.2.1, if
 
38
 * you use libkse (see `man libmap.conf`).
 
39
 *
 
40
 * For NetBSD, use at least 2.0.
 
41
 *
 
42
 * For Linux, you should use a 2.6 kernel, and make sure your glibc has epoll
 
43
 * support compiled in.
 
44
 *
 
45
 */
 
46
 
 
47
#include "apr.h"
 
48
#include "apr_portable.h"
 
49
#include "apr_strings.h"
 
50
#include "apr_file_io.h"
 
51
#include "apr_thread_proc.h"
 
52
#include "apr_signal.h"
 
53
#include "apr_thread_mutex.h"
 
54
#include "apr_proc_mutex.h"
 
55
#include "apr_poll.h"
 
56
#include "apr_ring.h"
 
57
#include "apr_queue.h"
 
58
#define APR_WANT_STRFUNC
 
59
#include "apr_want.h"
 
60
 
 
61
#if APR_HAVE_UNISTD_H
 
62
#include <unistd.h>
 
63
#endif
 
64
#if APR_HAVE_SYS_SOCKET_H
 
65
#include <sys/socket.h>
 
66
#endif
 
67
#if APR_HAVE_SYS_WAIT_H
 
68
#include <sys/wait.h>
 
69
#endif
 
70
#ifdef HAVE_SYS_PROCESSOR_H
 
71
#include <sys/processor.h>      /* for bindprocessor() */
 
72
#endif
 
73
 
 
74
#if !APR_HAS_THREADS
 
75
#error The Event MPM requires APR threads, but they are unavailable.
 
76
#endif
 
77
 
 
78
#define CORE_PRIVATE
 
79
 
 
80
#include "ap_config.h"
 
81
#include "httpd.h"
 
82
#include "http_main.h"
 
83
#include "http_log.h"
 
84
#include "http_config.h"        /* for read_config */
 
85
#include "http_core.h"          /* for get_remote_host */
 
86
#include "http_connection.h"
 
87
#include "ap_mpm.h"
 
88
#include "pod.h"
 
89
#include "mpm_common.h"
 
90
#include "ap_listen.h"
 
91
#include "scoreboard.h"
 
92
#include "fdqueue.h"
 
93
#include "mpm_default.h"
 
94
#include "http_vhost.h"
 
95
 
 
96
#include <signal.h>
 
97
#include <limits.h>             /* for INT_MAX */
 
98
 
 
99
/* Limit on the total --- clients will be locked out if more servers than
 
100
 * this are needed.  It is intended solely to keep the server from crashing
 
101
 * when things get out of hand.
 
102
 *
 
103
 * We keep a hard maximum number of servers, for two reasons --- first off,
 
104
 * in case something goes seriously wrong, we want to stop the fork bomb
 
105
 * short of actually crashing the machine we're running on by filling some
 
106
 * kernel table.  Secondly, it keeps the size of the scoreboard file small
 
107
 * enough that we can read the whole thing without worrying too much about
 
108
 * the overhead.
 
109
 */
 
110
#ifndef DEFAULT_SERVER_LIMIT
 
111
#define DEFAULT_SERVER_LIMIT 16
 
112
#endif
 
113
 
 
114
/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT.  We want
 
115
 * some sort of compile-time limit to help catch typos.
 
116
 */
 
117
#ifndef MAX_SERVER_LIMIT
 
118
#define MAX_SERVER_LIMIT 20000
 
119
#endif
 
120
 
 
121
/* Limit on the threads per process.  Clients will be locked out if more than
 
122
 * this are needed.
 
123
 *
 
124
 * We keep this for one reason it keeps the size of the scoreboard file small
 
125
 * enough that we can read the whole thing without worrying too much about
 
126
 * the overhead.
 
127
 */
 
128
#ifndef DEFAULT_THREAD_LIMIT
 
129
#define DEFAULT_THREAD_LIMIT 64
 
130
#endif
 
131
 
 
132
/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT.  We want
 
133
 * some sort of compile-time limit to help catch typos.
 
134
 */
 
135
#ifndef MAX_THREAD_LIMIT
 
136
#define MAX_THREAD_LIMIT 100000
 
137
#endif
 
138
 
 
139
/*
 
140
 * Actual definitions of config globals
 
141
 */
 
142
 
 
143
int ap_threads_per_child = 0;   /* Worker threads per child */
 
144
static int ap_daemons_to_start = 0;
 
145
static int min_spare_threads = 0;
 
146
static int max_spare_threads = 0;
 
147
static int ap_daemons_limit = 0;
 
148
static int server_limit = DEFAULT_SERVER_LIMIT;
 
149
static int first_server_limit = 0;
 
150
static int thread_limit = DEFAULT_THREAD_LIMIT;
 
151
static int first_thread_limit = 0;
 
152
static int changed_limit_at_restart;
 
153
static int dying = 0;
 
154
static int workers_may_exit = 0;
 
155
static int start_thread_may_exit = 0;
 
156
static int listener_may_exit = 0;
 
157
static int requests_this_child;
 
158
static int num_listensocks = 0;
 
159
static int resource_shortage = 0;
 
160
static fd_queue_t *worker_queue;
 
161
static fd_queue_info_t *worker_queue_info;
 
162
static int mpm_state = AP_MPMQ_STARTING;
 
163
static int sick_child_detected;
 
164
 
 
165
apr_thread_mutex_t *timeout_mutex;
 
166
APR_RING_HEAD(timeout_head_t, conn_state_t);
 
167
static struct timeout_head_t timeout_head;
 
168
 
 
169
static apr_pollset_t *event_pollset;
 
170
 
 
171
/* The structure used to pass unique initialization info to each thread */
 
172
typedef struct
 
173
{
 
174
    int pid;
 
175
    int tid;
 
176
    int sd;
 
177
} proc_info;
 
178
 
 
179
/* Structure used to pass information to the thread responsible for
 
180
 * creating the rest of the threads.
 
181
 */
 
182
typedef struct
 
183
{
 
184
    apr_thread_t **threads;
 
185
    apr_thread_t *listener;
 
186
    int child_num_arg;
 
187
    apr_threadattr_t *threadattr;
 
188
} thread_starter;
 
189
 
 
190
typedef enum
 
191
{
 
192
    PT_CSD,
 
193
    PT_ACCEPT
 
194
} poll_type_e;
 
195
 
 
196
typedef struct
 
197
{
 
198
    poll_type_e type;
 
199
    int status;        /*XXX what is this for?  0 and 1 don't make it clear */
 
200
    void *baton;
 
201
} listener_poll_type;
 
202
 
 
203
#define ID_FROM_CHILD_THREAD(c, t)    ((c * thread_limit) + t)
 
204
 
 
205
/*
 
206
 * The max child slot ever assigned, preserved across restarts.  Necessary
 
207
 * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts.  We
 
208
 * use this value to optimize routines that have to scan the entire
 
209
 * scoreboard.
 
210
 */
 
211
int ap_max_daemons_limit = -1;
 
212
 
 
213
static ap_pod_t *pod;
 
214
 
 
215
/* *Non*-shared http_main globals... */
 
216
 
 
217
server_rec *ap_server_conf;
 
218
 
 
219
/* The worker MPM respects a couple of runtime flags that can aid
 
220
 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
 
221
 * from detaching from its controlling terminal. Additionally, setting
 
222
 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
 
223
 * child_main loop running in the process which originally started up.
 
224
 * This gives you a pretty nice debugging environment.  (You'll get a SIGHUP
 
225
 * early in standalone_main; just continue through.  This is the server
 
226
 * trying to kill off any child processes which it might have lying
 
227
 * around --- Apache doesn't keep track of their pids, it just sends
 
228
 * SIGHUP to the process group, ignoring it in the root process.
 
229
 * Continue through and you'll be fine.).
 
230
 */
 
231
 
 
232
static int one_process = 0;
 
233
 
 
234
#ifdef DEBUG_SIGSTOP
 
235
int raise_sigstop_flags;
 
236
#endif
 
237
 
 
238
static apr_pool_t *pconf;       /* Pool for config stuff */
 
239
static apr_pool_t *pchild;      /* Pool for httpd child stuff */
 
240
 
 
241
static pid_t ap_my_pid;         /* Linux getpid() doesn't work except in main
 
242
                                   thread. Use this instead */
 
243
static pid_t parent_pid;
 
244
static apr_os_thread_t *listener_os_thread;
 
245
 
 
246
/* The LISTENER_SIGNAL signal will be sent from the main thread to the
 
247
 * listener thread to wake it up for graceful termination (what a child
 
248
 * process from an old generation does when the admin does "apachectl
 
249
 * graceful").  This signal will be blocked in all threads of a child
 
250
 * process except for the listener thread.
 
251
 */
 
252
#define LISTENER_SIGNAL     SIGHUP
 
253
 
 
254
/* An array of socket descriptors in use by each thread used to
 
255
 * perform a non-graceful (forced) shutdown of the server.
 
256
 */
 
257
static apr_socket_t **worker_sockets;
 
258
 
 
259
static void close_worker_sockets(void)
 
260
{
 
261
    int i;
 
262
    for (i = 0; i < ap_threads_per_child; i++) {
 
263
        if (worker_sockets[i]) {
 
264
            apr_socket_close(worker_sockets[i]);
 
265
            worker_sockets[i] = NULL;
 
266
        }
 
267
    }
 
268
}
 
269
 
 
270
static void wakeup_listener(void)
 
271
{
 
272
    listener_may_exit = 1;
 
273
    if (!listener_os_thread) {
 
274
        /* XXX there is an obscure path that this doesn't handle perfectly:
 
275
         *     right after listener thread is created but before
 
276
         *     listener_os_thread is set, the first worker thread hits an
 
277
         *     error and starts graceful termination
 
278
         */
 
279
        return;
 
280
    }
 
281
    /*
 
282
     * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
 
283
     * platforms and wake up the listener thread since it is the only thread
 
284
     * with SIGHUP unblocked, but that doesn't work on Linux
 
285
     */
 
286
#ifdef HAVE_PTHREAD_KILL
 
287
    pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
 
288
#else
 
289
    kill(ap_my_pid, LISTENER_SIGNAL);
 
290
#endif
 
291
}
 
292
 
 
293
#define ST_INIT              0
 
294
#define ST_GRACEFUL          1
 
295
#define ST_UNGRACEFUL        2
 
296
 
 
297
static int terminate_mode = ST_INIT;
 
298
 
 
299
static void signal_threads(int mode)
 
300
{
 
301
    if (terminate_mode == mode) {
 
302
        return;
 
303
    }
 
304
    terminate_mode = mode;
 
305
    mpm_state = AP_MPMQ_STOPPING;
 
306
 
 
307
    /* in case we weren't called from the listener thread, wake up the
 
308
     * listener thread
 
309
     */
 
310
    wakeup_listener();
 
311
 
 
312
    /* for ungraceful termination, let the workers exit now;
 
313
     * for graceful termination, the listener thread will notify the
 
314
     * workers to exit once it has stopped accepting new connections
 
315
     */
 
316
    if (mode == ST_UNGRACEFUL) {
 
317
        workers_may_exit = 1;
 
318
        ap_queue_interrupt_all(worker_queue);
 
319
        ap_queue_info_term(worker_queue_info);
 
320
        close_worker_sockets(); /* forcefully kill all current connections */
 
321
    }
 
322
}
 
323
 
 
324
AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
 
325
{
 
326
    switch (query_code) {
 
327
    case AP_MPMQ_MAX_DAEMON_USED:
 
328
        *result = ap_max_daemons_limit;
 
329
        return APR_SUCCESS;
 
330
    case AP_MPMQ_IS_THREADED:
 
331
        *result = AP_MPMQ_STATIC;
 
332
        return APR_SUCCESS;
 
333
    case AP_MPMQ_IS_FORKED:
 
334
        *result = AP_MPMQ_DYNAMIC;
 
335
        return APR_SUCCESS;
 
336
    case AP_MPMQ_IS_ASYNC:
 
337
        *result = 1;
 
338
        return APR_SUCCESS;
 
339
    case AP_MPMQ_HARD_LIMIT_DAEMONS:
 
340
        *result = server_limit;
 
341
        return APR_SUCCESS;
 
342
    case AP_MPMQ_HARD_LIMIT_THREADS:
 
343
        *result = thread_limit;
 
344
        return APR_SUCCESS;
 
345
    case AP_MPMQ_MAX_THREADS:
 
346
        *result = ap_threads_per_child;
 
347
        return APR_SUCCESS;
 
348
    case AP_MPMQ_MIN_SPARE_DAEMONS:
 
349
        *result = 0;
 
350
        return APR_SUCCESS;
 
351
    case AP_MPMQ_MIN_SPARE_THREADS:
 
352
        *result = min_spare_threads;
 
353
        return APR_SUCCESS;
 
354
    case AP_MPMQ_MAX_SPARE_DAEMONS:
 
355
        *result = 0;
 
356
        return APR_SUCCESS;
 
357
    case AP_MPMQ_MAX_SPARE_THREADS:
 
358
        *result = max_spare_threads;
 
359
        return APR_SUCCESS;
 
360
    case AP_MPMQ_MAX_REQUESTS_DAEMON:
 
361
        *result = ap_max_requests_per_child;
 
362
        return APR_SUCCESS;
 
363
    case AP_MPMQ_MAX_DAEMONS:
 
364
        *result = ap_daemons_limit;
 
365
        return APR_SUCCESS;
 
366
    case AP_MPMQ_MPM_STATE:
 
367
        *result = mpm_state;
 
368
        return APR_SUCCESS;
 
369
    }
 
370
    return APR_ENOTIMPL;
 
371
}
 
372
 
 
373
/* a clean exit from a child with proper cleanup */
 
374
static void clean_child_exit(int code) __attribute__ ((noreturn));
 
375
static void clean_child_exit(int code)
 
376
{
 
377
    mpm_state = AP_MPMQ_STOPPING;
 
378
    if (pchild) {
 
379
        apr_pool_destroy(pchild);
 
380
    }
 
381
    exit(code);
 
382
}
 
383
 
 
384
static void just_die(int sig)
 
385
{
 
386
    clean_child_exit(0);
 
387
}
 
388
 
 
389
/*****************************************************************
 
390
 * Connection structures and accounting...
 
391
 */
 
392
 
 
393
/* volatile just in case */
 
394
static int volatile shutdown_pending;
 
395
static int volatile restart_pending;
 
396
static int volatile is_graceful;
 
397
static volatile int child_fatal;
 
398
ap_generation_t volatile ap_my_generation;
 
399
 
 
400
/*
 
401
 * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
 
402
 * functions to initiate shutdown or restart without relying on signals.
 
403
 * Previously this was initiated in sig_term() and restart() signal handlers,
 
404
 * but we want to be able to start a shutdown/restart from other sources --
 
405
 * e.g. on Win32, from the service manager. Now the service manager can
 
406
 * call ap_start_shutdown() or ap_start_restart() as appropiate.  Note that
 
407
 * these functions can also be called by the child processes, since global
 
408
 * variables are no longer used to pass on the required action to the parent.
 
409
 *
 
410
 * These should only be called from the parent process itself, since the
 
411
 * parent process will use the shutdown_pending and restart_pending variables
 
412
 * to determine whether to shutdown or restart. The child process should
 
413
 * call signal_parent() directly to tell the parent to die -- this will
 
414
 * cause neither of those variable to be set, which the parent will
 
415
 * assume means something serious is wrong (which it will be, for the
 
416
 * child to force an exit) and so do an exit anyway.
 
417
 */
 
418
 
 
419
static void ap_start_shutdown(int graceful)
 
420
{
 
421
    mpm_state = AP_MPMQ_STOPPING;
 
422
    if (shutdown_pending == 1) {
 
423
        /* Um, is this _probably_ not an error, if the user has
 
424
         * tried to do a shutdown twice quickly, so we won't
 
425
         * worry about reporting it.
 
426
         */
 
427
        return;
 
428
    }
 
429
    shutdown_pending = 1;
 
430
    is_graceful = graceful;
 
431
}
 
432
 
 
433
/* do a graceful restart if graceful == 1 */
 
434
static void ap_start_restart(int graceful)
 
435
{
 
436
    mpm_state = AP_MPMQ_STOPPING;
 
437
    if (restart_pending == 1) {
 
438
        /* Probably not an error - don't bother reporting it */
 
439
        return;
 
440
    }
 
441
    restart_pending = 1;
 
442
    is_graceful = graceful;
 
443
}
 
444
 
 
445
static void sig_term(int sig)
 
446
{
 
447
    ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
 
448
}
 
449
 
 
450
static void restart(int sig)
 
451
{
 
452
    ap_start_restart(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,
 
472
                     "sigaction(SIGTERM)");
 
473
#ifdef AP_SIG_GRACEFUL_STOP
 
474
    if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
 
475
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
 
476
                     "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
 
477
#endif
 
478
#ifdef SIGINT
 
479
    if (sigaction(SIGINT, &sa, NULL) < 0)
 
480
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
 
481
                     "sigaction(SIGINT)");
 
482
#endif
 
483
#ifdef SIGXCPU
 
484
    sa.sa_handler = SIG_DFL;
 
485
    if (sigaction(SIGXCPU, &sa, NULL) < 0)
 
486
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
 
487
                     "sigaction(SIGXCPU)");
 
488
#endif
 
489
#ifdef SIGXFSZ
 
490
    sa.sa_handler = SIG_DFL;
 
491
    if (sigaction(SIGXFSZ, &sa, NULL) < 0)
 
492
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
 
493
                     "sigaction(SIGXFSZ)");
 
494
#endif
 
495
#ifdef SIGPIPE
 
496
    sa.sa_handler = SIG_IGN;
 
497
    if (sigaction(SIGPIPE, &sa, NULL) < 0)
 
498
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
 
499
                     "sigaction(SIGPIPE)");
 
500
#endif
 
501
 
 
502
    /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
 
503
     * processing one */
 
504
    sigaddset(&sa.sa_mask, SIGHUP);
 
505
    sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
 
506
    sa.sa_handler = restart;
 
507
    if (sigaction(SIGHUP, &sa, NULL) < 0)
 
508
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
 
509
                     "sigaction(SIGHUP)");
 
510
    if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
 
511
        ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
 
512
                     "sigaction(" AP_SIG_GRACEFUL_STRING ")");
 
513
#else
 
514
    if (!one_process) {
 
515
#ifdef SIGXCPU
 
516
        apr_signal(SIGXCPU, SIG_DFL);
 
517
#endif /* SIGXCPU */
 
518
#ifdef SIGXFSZ
 
519
        apr_signal(SIGXFSZ, SIG_DFL);
 
520
#endif /* SIGXFSZ */
 
521
    }
 
522
 
 
523
    apr_signal(SIGTERM, sig_term);
 
524
#ifdef SIGHUP
 
525
    apr_signal(SIGHUP, restart);
 
526
#endif /* SIGHUP */
 
527
#ifdef AP_SIG_GRACEFUL
 
528
    apr_signal(AP_SIG_GRACEFUL, restart);
 
529
#endif /* AP_SIG_GRACEFUL */
 
530
#ifdef AP_SIG_GRACEFUL_STOP
 
531
     apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
 
532
#endif /* AP_SIG_GRACEFUL_STOP */
 
533
#ifdef SIGPIPE
 
534
    apr_signal(SIGPIPE, SIG_IGN);
 
535
#endif /* SIGPIPE */
 
536
 
 
537
#endif
 
538
}
 
539
 
 
540
/*****************************************************************
 
541
 * Here follows a long bunch of generic server bookkeeping stuff...
 
542
 */
 
543
 
 
544
int ap_graceful_stop_signalled(void)
 
545
    /* XXX this is really a bad confusing obsolete name
 
546
     * maybe it should be ap_mpm_process_exiting?
 
547
     */
 
548
{
 
549
    /* note: for a graceful termination, listener_may_exit will be set before
 
550
     *       workers_may_exit, so check listener_may_exit
 
551
     */
 
552
    return listener_may_exit;
 
553
}
 
554
 
 
555
/*****************************************************************
 
556
 * Child process main loop.
 
557
 */
 
558
 
 
559
static int process_socket(apr_pool_t * p, apr_socket_t * sock,
 
560
                          conn_state_t * cs, int my_child_num,
 
561
                          int my_thread_num)
 
562
{
 
563
    conn_rec *c;
 
564
    listener_poll_type *pt;
 
565
    long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
 
566
    int csd;
 
567
    int rc;
 
568
    apr_time_t time_now = 0;
 
569
    ap_sb_handle_t *sbh;
 
570
 
 
571
    ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
 
572
    apr_os_sock_get(&csd, sock);
 
573
 
 
574
    time_now = apr_time_now();
 
575
 
 
576
    if (cs == NULL) {           /* This is a new connection */
 
577
 
 
578
        cs = apr_pcalloc(p, sizeof(conn_state_t));
 
579
 
 
580
        pt = apr_pcalloc(p, sizeof(*pt));
 
581
 
 
582
        cs->bucket_alloc = apr_bucket_alloc_create(p);
 
583
        c = ap_run_create_connection(p, ap_server_conf, sock,
 
584
                                     conn_id, sbh, cs->bucket_alloc);
 
585
        cs->c = c;
 
586
        c->cs = cs;
 
587
        cs->p = p;
 
588
        cs->pfd.desc_type = APR_POLL_SOCKET;
 
589
        cs->pfd.reqevents = APR_POLLIN;
 
590
        cs->pfd.desc.s = sock;
 
591
        pt->type = PT_CSD;
 
592
        pt->status = 1;
 
593
        pt->baton = cs;
 
594
        cs->pfd.client_data = pt;
 
595
 
 
596
        ap_update_vhost_given_ip(c);
 
597
 
 
598
        rc = ap_run_pre_connection(c, sock);
 
599
        if (rc != OK && rc != DONE) {
 
600
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
 
601
                         "process_socket: connection aborted");
 
602
            c->aborted = 1;
 
603
        }
 
604
 
 
605
        /**
 
606
         * XXX If the platform does not have a usable way of bundling
 
607
         * accept() with a socket readability check, like Win32,
 
608
         * and there are measurable delays before the
 
609
         * socket is readable due to the first data packet arriving,
 
610
         * it might be better to create the cs on the listener thread
 
611
         * with the state set to CONN_STATE_CHECK_REQUEST_LINE_READABLE
 
612
         *
 
613
         * FreeBSD users will want to enable the HTTP accept filter
 
614
         * module in their kernel for the highest performance
 
615
         * When the accept filter is active, sockets are kept in the
 
616
         * kernel until a HTTP request is received.
 
617
         */
 
618
        cs->state = CONN_STATE_READ_REQUEST_LINE;
 
619
 
 
620
    }
 
621
    else {
 
622
        c = cs->c;
 
623
        c->sbh = sbh;
 
624
    }
 
625
 
 
626
    if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
 
627
        if (!c->aborted) {
 
628
            ap_run_process_connection(c);
 
629
 
 
630
            /* state will be updated upon return
 
631
             * fall thru to either wait for readability/timeout or
 
632
             * do lingering close
 
633
             */
 
634
        }
 
635
        else {
 
636
            cs->state = CONN_STATE_LINGER;
 
637
        }
 
638
    }
 
639
 
 
640
    if (cs->state == CONN_STATE_LINGER) {
 
641
        ap_lingering_close(c);
 
642
        apr_bucket_alloc_destroy(cs->bucket_alloc);
 
643
        apr_pool_clear(p);
 
644
        ap_push_pool(worker_queue_info, p);
 
645
        return 1;
 
646
    }
 
647
    else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
 
648
        apr_status_t rc;
 
649
        listener_poll_type *pt = (listener_poll_type *) cs->pfd.client_data;
 
650
 
 
651
        /* It greatly simplifies the logic to use a single timeout value here
 
652
         * because the new element can just be added to the end of the list and
 
653
         * it will stay sorted in expiration time sequence.  If brand new
 
654
         * sockets are sent to the event thread for a readability check, this
 
655
         * will be a slight behavior change - they use the non-keepalive
 
656
         * timeout today.  With a normal client, the socket will be readable in
 
657
         * a few milliseconds anyway.
 
658
         */
 
659
        cs->expiration_time = ap_server_conf->keep_alive_timeout + time_now;
 
660
        apr_thread_mutex_lock(timeout_mutex);
 
661
        APR_RING_INSERT_TAIL(&timeout_head, cs, conn_state_t, timeout_list);
 
662
 
 
663
        pt->status = 0;
 
664
        /* Add work to pollset. These are always read events */
 
665
        rc = apr_pollset_add(event_pollset, &cs->pfd);
 
666
 
 
667
        apr_thread_mutex_unlock(timeout_mutex);
 
668
 
 
669
        if (rc != APR_SUCCESS) {
 
670
            ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
 
671
                         "process_socket: apr_pollset_add failure");
 
672
            AP_DEBUG_ASSERT(rc == APR_SUCCESS);
 
673
        }
 
674
    }
 
675
    return 0;
 
676
}
 
677
 
 
678
/* requests_this_child has gone to zero or below.  See if the admin coded
 
679
   "MaxRequestsPerChild 0", and keep going in that case.  Doing it this way
 
680
   simplifies the hot path in worker_thread */
 
681
static void check_infinite_requests(void)
 
682
{
 
683
    if (ap_max_requests_per_child) {
 
684
        signal_threads(ST_GRACEFUL);
 
685
    }
 
686
    else {
 
687
        /* wow! if you're executing this code, you may have set a record.
 
688
         * either this child process has served over 2 billion requests, or
 
689
         * you're running a threaded 2.0 on a 16 bit machine.
 
690
         *
 
691
         * I'll buy pizza and beers at Apachecon for the first person to do
 
692
         * the former without cheating (dorking with INT_MAX, or running with
 
693
         * uncommitted performance patches, for example).
 
694
         *
 
695
         * for the latter case, you probably deserve a beer too.   Greg Ames
 
696
         */
 
697
 
 
698
        requests_this_child = INT_MAX;  /* keep going */
 
699
    }
 
700
}
 
701
 
 
702
static void unblock_signal(int sig)
 
703
{
 
704
    sigset_t sig_mask;
 
705
 
 
706
    sigemptyset(&sig_mask);
 
707
    sigaddset(&sig_mask, sig);
 
708
#if defined(SIGPROCMASK_SETS_THREAD_MASK)
 
709
    sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
 
710
#else
 
711
    pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
 
712
#endif
 
713
}
 
714
 
 
715
static void dummy_signal_handler(int sig)
 
716
{
 
717
    /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
 
718
     *     then we don't need this goofy function.
 
719
     */
 
720
}
 
721
 
 
722
static apr_status_t push2worker(const apr_pollfd_t * pfd,
 
723
                                apr_pollset_t * pollset)
 
724
{
 
725
    listener_poll_type *pt = (listener_poll_type *) pfd->client_data;
 
726
    conn_state_t *cs = (conn_state_t *) pt->baton;
 
727
    apr_status_t rc;
 
728
 
 
729
    if (pt->status == 1) {
 
730
        return 0;
 
731
    }
 
732
 
 
733
    pt->status = 1;
 
734
 
 
735
    rc = apr_pollset_remove(pollset, pfd);
 
736
 
 
737
    /*
 
738
     * Some of the pollset backends, like KQueue or Epoll
 
739
     * automagically remove the FD if the socket is closed,
 
740
     * therefore, we can accept _SUCCESS or _NOTFOUND,
 
741
     * and we still want to keep going
 
742
     */
 
743
    if (rc != APR_SUCCESS && rc != APR_NOTFOUND) {
 
744
        cs->state = CONN_STATE_LINGER;
 
745
    }
 
746
 
 
747
    rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);
 
748
    if (rc != APR_SUCCESS) {
 
749
        /* trash the connection; we couldn't queue the connected
 
750
         * socket to a worker
 
751
         */
 
752
        apr_bucket_alloc_destroy(cs->bucket_alloc);
 
753
        apr_socket_close(cs->pfd.desc.s);
 
754
        ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
 
755
                     ap_server_conf, "push2worker: ap_queue_push failed");
 
756
        apr_pool_clear(cs->p);
 
757
        ap_push_pool(worker_queue_info, cs->p);
 
758
    }
 
759
 
 
760
    return APR_SUCCESS;
 
761
}
 
762
 
 
763
/* get_worker:
 
764
 *     reserve a worker thread, block if all are currently busy.
 
765
 *     this prevents the worker queue from overflowing and lets
 
766
 *     other processes accept new connections in the mean time.
 
767
 */
 
768
static int get_worker(int *have_idle_worker_p)
 
769
{
 
770
    apr_status_t rc;
 
771
 
 
772
    if (!*have_idle_worker_p) {
 
773
        rc = ap_queue_info_wait_for_idler(worker_queue_info);
 
774
 
 
775
        if (rc == APR_SUCCESS) {
 
776
            *have_idle_worker_p = 1;
 
777
            return 1;
 
778
        }
 
779
        else {
 
780
            if (!APR_STATUS_IS_EOF(rc)) {
 
781
                ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
 
782
                             "ap_queue_info_wait_for_idler failed.  "
 
783
                             "Attempting to shutdown process gracefully");
 
784
                signal_threads(ST_GRACEFUL);
 
785
            }
 
786
            return 0;
 
787
        }
 
788
    }
 
789
    else {
 
790
        /* already reserved a worker thread - must have hit a
 
791
         * transient error on a previous pass
 
792
         */
 
793
        return 1;
 
794
    }
 
795
}
 
796
 
 
797
static void *listener_thread(apr_thread_t * thd, void *dummy)
 
798
{
 
799
    apr_status_t rc;
 
800
    proc_info *ti = dummy;
 
801
    int process_slot = ti->pid;
 
802
    apr_pool_t *tpool = apr_thread_pool_get(thd);
 
803
    void *csd = NULL;
 
804
    apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
 
805
    ap_listen_rec *lr;
 
806
    int have_idle_worker = 0;
 
807
    conn_state_t *cs;
 
808
    const apr_pollfd_t *out_pfd;
 
809
    apr_int32_t num = 0;
 
810
    apr_time_t time_now = 0;
 
811
    apr_interval_time_t timeout_interval;
 
812
    apr_time_t timeout_time;
 
813
    listener_poll_type *pt;
 
814
 
 
815
    free(ti);
 
816
 
 
817
    /* We set this to force apr_pollset to wakeup if there hasn't been any IO
 
818
     * on any of its sockets.  This allows sockets to have been added
 
819
     * when no other keepalive operations where going on.
 
820
     *
 
821
     * current value is 1 second
 
822
     */
 
823
    timeout_interval = 1000000;
 
824
 
 
825
    /* the following times out events that are really close in the future
 
826
     *   to prevent extra poll calls
 
827
     *
 
828
     * current value is .1 second
 
829
     */
 
830
#define TIMEOUT_FUDGE_FACTOR 100000
 
831
 
 
832
    /* POLLSET_SCALE_FACTOR * ap_threads_per_child sets the size of
 
833
     * the pollset.  I've seen 15 connections per active worker thread
 
834
     * running SPECweb99.
 
835
     *
 
836
     * However, with the newer apr_pollset, this is the number of sockets that
 
837
     * we will return to any *one* call to poll().  Therefore, there is no
 
838
     * reason to make it more than ap_threads_per_child.
 
839
     */
 
840
#define POLLSET_SCALE_FACTOR 1
 
841
 
 
842
    rc = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
 
843
                                 tpool);
 
844
    if (rc != APR_SUCCESS) {
 
845
        ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
 
846
                     "creation of the timeout mutex failed.  Attempting to "
 
847
                     "shutdown process gracefully");
 
848
        signal_threads(ST_GRACEFUL);
 
849
        return NULL;
 
850
    }
 
851
 
 
852
    APR_RING_INIT(&timeout_head, conn_state_t, timeout_list);
 
853
 
 
854
    /* Create the main pollset */
 
855
    rc = apr_pollset_create(&event_pollset,
 
856
                            ap_threads_per_child * POLLSET_SCALE_FACTOR,
 
857
                            tpool, APR_POLLSET_THREADSAFE);
 
858
    if (rc != APR_SUCCESS) {
 
859
        ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
 
860
                     "apr_pollset_create with Thread Safety failed. "
 
861
                     "Attempting to shutdown process gracefully");
 
862
        signal_threads(ST_GRACEFUL);
 
863
        return NULL;
 
864
    }
 
865
 
 
866
    for (lr = ap_listeners; lr != NULL; lr = lr->next) {
 
867
        apr_pollfd_t pfd = { 0 };
 
868
        pt = apr_pcalloc(tpool, sizeof(*pt));
 
869
        pfd.desc_type = APR_POLL_SOCKET;
 
870
        pfd.desc.s = lr->sd;
 
871
        pfd.reqevents = APR_POLLIN;
 
872
 
 
873
        pt->type = PT_ACCEPT;
 
874
        pt->baton = lr;
 
875
 
 
876
        pfd.client_data = pt;
 
877
 
 
878
        apr_socket_opt_set(pfd.desc.s, APR_SO_NONBLOCK, 1);
 
879
        apr_pollset_add(event_pollset, &pfd);
 
880
    }
 
881
 
 
882
    /* Unblock the signal used to wake this thread up, and set a handler for
 
883
     * it.
 
884
     */
 
885
    unblock_signal(LISTENER_SIGNAL);
 
886
    apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
 
887
 
 
888
    while (!listener_may_exit) {
 
889
 
 
890
        if (requests_this_child <= 0) {
 
891
            check_infinite_requests();
 
892
        }
 
893
 
 
894
        rc = apr_pollset_poll(event_pollset, timeout_interval, &num,
 
895
                              &out_pfd);
 
896
 
 
897
        if (rc != APR_SUCCESS) {
 
898
            if (APR_STATUS_IS_EINTR(rc)) {
 
899
                continue;
 
900
            }
 
901
            if (!APR_STATUS_IS_TIMEUP(rc)) {
 
902
                ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
 
903
                             "apr_pollset_poll failed.  Attempting to "
 
904
                             "shutdown process gracefully");
 
905
                signal_threads(ST_GRACEFUL);
 
906
            }
 
907
        }
 
908
 
 
909
        if (listener_may_exit)
 
910
            break;
 
911
 
 
912
        while (num && get_worker(&have_idle_worker)) {
 
913
            pt = (listener_poll_type *) out_pfd->client_data;
 
914
            if (pt->type == PT_CSD) {
 
915
                /* one of the sockets is readable */
 
916
                cs = (conn_state_t *) pt->baton;
 
917
                switch (cs->state) {
 
918
                case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
 
919
                    cs->state = CONN_STATE_READ_REQUEST_LINE;
 
920
                    break;
 
921
                default:
 
922
                    ap_log_error(APLOG_MARK, APLOG_ERR, rc,
 
923
                                 ap_server_conf,
 
924
                                 "event_loop: unexpected state %d",
 
925
                                 cs->state);
 
926
                    AP_DEBUG_ASSERT(0);
 
927
                }
 
928
 
 
929
                apr_thread_mutex_lock(timeout_mutex);
 
930
                APR_RING_REMOVE(cs, timeout_list);
 
931
                apr_thread_mutex_unlock(timeout_mutex);
 
932
 
 
933
                rc = push2worker(out_pfd, event_pollset);
 
934
                if (rc != APR_SUCCESS) {
 
935
                    ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
 
936
                                 ap_server_conf, "push2worker failed");
 
937
                }
 
938
                else {
 
939
                    have_idle_worker = 0;
 
940
                }
 
941
            }
 
942
            else {
 
943
                /* A Listener Socket is ready for an accept() */
 
944
                apr_pool_t *recycled_pool = NULL;
 
945
 
 
946
                lr = (ap_listen_rec *) pt->baton;
 
947
 
 
948
                ap_pop_pool(&recycled_pool, worker_queue_info);
 
949
 
 
950
                if (recycled_pool == NULL) {
 
951
                    /* create a new transaction pool for each accepted socket */
 
952
                    apr_allocator_t *allocator;
 
953
 
 
954
                    apr_allocator_create(&allocator);
 
955
                    apr_allocator_max_free_set(allocator,
 
956
                                               ap_max_mem_free);
 
957
                    apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
 
958
                    apr_allocator_owner_set(allocator, ptrans);
 
959
                    if (ptrans == NULL) {
 
960
                        ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
 
961
                                     ap_server_conf,
 
962
                                     "Failed to create transaction pool");
 
963
                        signal_threads(ST_GRACEFUL);
 
964
                        return NULL;
 
965
                    }
 
966
                }
 
967
                else {
 
968
                    ptrans = recycled_pool;
 
969
                }
 
970
 
 
971
                apr_pool_tag(ptrans, "transaction");
 
972
 
 
973
                rc = lr->accept_func(&csd, lr, ptrans);
 
974
 
 
975
                /* later we trash rv and rely on csd to indicate
 
976
                 * success/failure
 
977
                 */
 
978
                AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
 
979
 
 
980
                if (rc == APR_EGENERAL) {
 
981
                    /* E[NM]FILE, ENOMEM, etc */
 
982
                    resource_shortage = 1;
 
983
                    signal_threads(ST_GRACEFUL);
 
984
                }
 
985
 
 
986
                if (csd != NULL) {
 
987
                    rc = ap_queue_push(worker_queue, csd, NULL, ptrans);
 
988
                    if (rc != APR_SUCCESS) {
 
989
                        /* trash the connection; we couldn't queue the connected
 
990
                         * socket to a worker
 
991
                         */
 
992
                        apr_socket_close(csd);
 
993
                        ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
 
994
                                     ap_server_conf,
 
995
                                     "ap_queue_push failed");
 
996
                        apr_pool_clear(ptrans);
 
997
                        ap_push_pool(worker_queue_info, ptrans);
 
998
                    }
 
999
                    else {
 
1000
                        have_idle_worker = 0;
 
1001
                    }
 
1002
                }
 
1003
                else {
 
1004
                    apr_pool_clear(ptrans);
 
1005
                    ap_push_pool(worker_queue_info, ptrans);
 
1006
                }
 
1007
            }               /* if:else on pt->type */
 
1008
            out_pfd++;
 
1009
            num--;
 
1010
        }                   /* while for processing poll */
 
1011
 
 
1012
        /* XXX possible optimization: stash the current time for use as
 
1013
         * r->request_time for new requests
 
1014
         */
 
1015
        time_now = apr_time_now();
 
1016
 
 
1017
        /* handle timed out sockets */
 
1018
        apr_thread_mutex_lock(timeout_mutex);
 
1019
 
 
1020
        cs = APR_RING_FIRST(&timeout_head);
 
1021
        timeout_time = time_now + TIMEOUT_FUDGE_FACTOR;
 
1022
        while (!APR_RING_EMPTY(&timeout_head, conn_state_t, timeout_list)
 
1023
               && cs->expiration_time < timeout_time
 
1024
               && get_worker(&have_idle_worker)) {
 
1025
 
 
1026
            cs->state = CONN_STATE_LINGER;
 
1027
 
 
1028
            APR_RING_REMOVE(cs, timeout_list);
 
1029
 
 
1030
            rc = push2worker(&cs->pfd, event_pollset);
 
1031
 
 
1032
            if (rc != APR_SUCCESS) {
 
1033
                return NULL;
 
1034
                /* XXX return NULL looks wrong - not an init failure
 
1035
                 * that bypasses all the cleanup outside the main loop
 
1036
                 * break seems more like it
 
1037
                 * need to evaluate seriousness of push2worker failures
 
1038
                 */
 
1039
            }
 
1040
            have_idle_worker = 0;
 
1041
            cs = APR_RING_FIRST(&timeout_head);
 
1042
        }
 
1043
        apr_thread_mutex_unlock(timeout_mutex);
 
1044
 
 
1045
    }     /* listener main loop */
 
1046
 
 
1047
    ap_close_listeners();
 
1048
    ap_queue_term(worker_queue);
 
1049
    dying = 1;
 
1050
    ap_scoreboard_image->parent[process_slot].quiescing = 1;
 
1051
 
 
1052
    /* wake up the main thread */
 
1053
    kill(ap_my_pid, SIGTERM);
 
1054
 
 
1055
    apr_thread_exit(thd, APR_SUCCESS);
 
1056
    return NULL;
 
1057
}
 
1058
 
 
1059
/* XXX For ungraceful termination/restart, we definitely don't want to
 
1060
 *     wait for active connections to finish but we may want to wait
 
1061
 *     for idle workers to get out of the queue code and release mutexes,
 
1062
 *     since those mutexes are cleaned up pretty soon and some systems
 
1063
 *     may not react favorably (i.e., segfault) if operations are attempted
 
1064
 *     on cleaned-up mutexes.
 
1065
 */
 
1066
static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
 
1067
{
 
1068
    proc_info *ti = dummy;
 
1069
    int process_slot = ti->pid;
 
1070
    int thread_slot = ti->tid;
 
1071
    apr_socket_t *csd = NULL;
 
1072
    conn_state_t *cs;
 
1073
    apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
 
1074
    apr_status_t rv;
 
1075
    int is_idle = 0;
 
1076
 
 
1077
    free(ti);
 
1078
 
 
1079
    ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
 
1080
    ap_scoreboard_image->servers[process_slot][thread_slot].generation = ap_my_generation;
 
1081
    ap_update_child_status_from_indexes(process_slot, thread_slot,
 
1082
                                        SERVER_STARTING, NULL);
 
1083
 
 
1084
    while (!workers_may_exit) {
 
1085
        if (!is_idle) {
 
1086
            rv = ap_queue_info_set_idle(worker_queue_info, NULL);
 
1087
            if (rv != APR_SUCCESS) {
 
1088
                ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
 
1089
                             "ap_queue_info_set_idle failed. Attempting to "
 
1090
                             "shutdown process gracefully.");
 
1091
                signal_threads(ST_GRACEFUL);
 
1092
                break;
 
1093
            }
 
1094
            is_idle = 1;
 
1095
        }
 
1096
 
 
1097
        ap_update_child_status_from_indexes(process_slot, thread_slot,
 
1098
                                            SERVER_READY, NULL);
 
1099
      worker_pop:
 
1100
        if (workers_may_exit) {
 
1101
            break;
 
1102
        }
 
1103
        rv = ap_queue_pop(worker_queue, &csd, &cs, &ptrans);
 
1104
 
 
1105
        if (rv != APR_SUCCESS) {
 
1106
            /* We get APR_EOF during a graceful shutdown once all the
 
1107
             * connections accepted by this server process have been handled.
 
1108
             */
 
1109
            if (APR_STATUS_IS_EOF(rv)) {
 
1110
                break;
 
1111
            }
 
1112
            /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
 
1113
             * from an explicit call to ap_queue_interrupt_all(). This allows
 
1114
             * us to unblock threads stuck in ap_queue_pop() when a shutdown
 
1115
             * is pending.
 
1116
             *
 
1117
             * If workers_may_exit is set and this is ungraceful termination/
 
1118
             * restart, we are bound to get an error on some systems (e.g.,
 
1119
             * AIX, which sanity-checks mutex operations) since the queue
 
1120
             * may have already been cleaned up.  Don't log the "error" if
 
1121
             * workers_may_exit is set.
 
1122
             */
 
1123
            else if (APR_STATUS_IS_EINTR(rv)) {
 
1124
                goto worker_pop;
 
1125
            }
 
1126
            /* We got some other error. */
 
1127
            else if (!workers_may_exit) {
 
1128
                ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
 
1129
                             "ap_queue_pop failed");
 
1130
            }
 
1131
            continue;
 
1132
        }
 
1133
        is_idle = 0;
 
1134
        worker_sockets[thread_slot] = csd;
 
1135
        rv = process_socket(ptrans, csd, cs, process_slot, thread_slot);
 
1136
        if (!rv) {
 
1137
            requests_this_child--;
 
1138
        }
 
1139
        worker_sockets[thread_slot] = NULL;
 
1140
    }
 
1141
 
 
1142
    ap_update_child_status_from_indexes(process_slot, thread_slot,
 
1143
                                        (dying) ? SERVER_DEAD :
 
1144
                                        SERVER_GRACEFUL,
 
1145
                                        (request_rec *) NULL);
 
1146
 
 
1147
    apr_thread_exit(thd, APR_SUCCESS);
 
1148
    return NULL;
 
1149
}
 
1150
 
 
1151
static int check_signal(int signum)
 
1152
{
 
1153
    switch (signum) {
 
1154
    case SIGTERM:
 
1155
    case SIGINT:
 
1156
        return 1;
 
1157
    }
 
1158
    return 0;
 
1159
}
 
1160
 
 
1161
 
 
1162
 
 
1163
static void create_listener_thread(thread_starter * ts)
 
1164
{
 
1165
    int my_child_num = ts->child_num_arg;
 
1166
    apr_threadattr_t *thread_attr = ts->threadattr;
 
1167
    proc_info *my_info;
 
1168
    apr_status_t rv;
 
1169
 
 
1170
    my_info = (proc_info *) malloc(sizeof(proc_info));
 
1171
    my_info->pid = my_child_num;
 
1172
    my_info->tid = -1;          /* listener thread doesn't have a thread slot */
 
1173
    my_info->sd = 0;
 
1174
    rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
 
1175
                           my_info, pchild);
 
1176
    if (rv != APR_SUCCESS) {
 
1177
        ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
 
1178
                     "apr_thread_create: unable to create listener thread");
 
1179
        /* let the parent decide how bad this really is */
 
1180
        clean_child_exit(APEXIT_CHILDSICK);
 
1181
    }
 
1182
    apr_os_thread_get(&listener_os_thread, ts->listener);
 
1183
}
 
1184
 
 
1185
/* XXX under some circumstances not understood, children can get stuck
 
1186
 *     in start_threads forever trying to take over slots which will
 
1187
 *     never be cleaned up; for now there is an APLOG_DEBUG message issued
 
1188
 *     every so often when this condition occurs
 
1189
 */
 
1190
static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
 
1191
{
 
1192
    thread_starter *ts = dummy;
 
1193
    apr_thread_t **threads = ts->threads;
 
1194
    apr_threadattr_t *thread_attr = ts->threadattr;
 
1195
    int child_num_arg = ts->child_num_arg;
 
1196
    int my_child_num = child_num_arg;
 
1197
    proc_info *my_info;
 
1198
    apr_status_t rv;
 
1199
    int i;
 
1200
    int threads_created = 0;
 
1201
    int listener_started = 0;
 
1202
    int loops;
 
1203
    int prev_threads_created;
 
1204
 
 
1205
    /* We must create the fd queues before we start up the listener
 
1206
     * and worker threads. */
 
1207
    worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
 
1208
    rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild);
 
1209
    if (rv != APR_SUCCESS) {
 
1210
        ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
 
1211
                     "ap_queue_init() failed");
 
1212
        clean_child_exit(APEXIT_CHILDFATAL);
 
1213
    }
 
1214
 
 
1215
    rv = ap_queue_info_create(&worker_queue_info, pchild,
 
1216
                              ap_threads_per_child);
 
1217
    if (rv != APR_SUCCESS) {
 
1218
        ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
 
1219
                     "ap_queue_info_create() failed");
 
1220
        clean_child_exit(APEXIT_CHILDFATAL);
 
1221
    }
 
1222
 
 
1223
    worker_sockets = apr_pcalloc(pchild, ap_threads_per_child
 
1224
                                 * sizeof(apr_socket_t *));
 
1225
 
 
1226
    loops = prev_threads_created = 0;
 
1227
    while (1) {
 
1228
        /* ap_threads_per_child does not include the listener thread */
 
1229
        for (i = 0; i < ap_threads_per_child; i++) {
 
1230
            int status =
 
1231
                ap_scoreboard_image->servers[child_num_arg][i].status;
 
1232
 
 
1233
            if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
 
1234
                continue;
 
1235
            }
 
1236
 
 
1237
            my_info = (proc_info *) malloc(sizeof(proc_info));
 
1238
            if (my_info == NULL) {
 
1239
                ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
 
1240
                             "malloc: out of memory");
 
1241
                clean_child_exit(APEXIT_CHILDFATAL);
 
1242
            }
 
1243
            my_info->pid = my_child_num;
 
1244
            my_info->tid = i;
 
1245
            my_info->sd = 0;
 
1246
 
 
1247
            /* We are creating threads right now */
 
1248
            ap_update_child_status_from_indexes(my_child_num, i,
 
1249
                                                SERVER_STARTING, NULL);
 
1250
            /* We let each thread update its own scoreboard entry.  This is
 
1251
             * done because it lets us deal with tid better.
 
1252
             */
 
1253
            rv = apr_thread_create(&threads[i], thread_attr,
 
1254
                                   worker_thread, my_info, pchild);
 
1255
            if (rv != APR_SUCCESS) {
 
1256
                ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
 
1257
                             "apr_thread_create: unable to create worker thread");
 
1258
                /* let the parent decide how bad this really is */
 
1259
                clean_child_exit(APEXIT_CHILDSICK);
 
1260
            }
 
1261
            threads_created++;
 
1262
        }
 
1263
 
 
1264
        /* Start the listener only when there are workers available */
 
1265
        if (!listener_started && threads_created) {
 
1266
            create_listener_thread(ts);
 
1267
            listener_started = 1;
 
1268
        }
 
1269
 
 
1270
 
 
1271
        if (start_thread_may_exit || threads_created == ap_threads_per_child) {
 
1272
            break;
 
1273
        }
 
1274
        /* wait for previous generation to clean up an entry */
 
1275
        apr_sleep(apr_time_from_sec(1));
 
1276
        ++loops;
 
1277
        if (loops % 120 == 0) { /* every couple of minutes */
 
1278
            if (prev_threads_created == threads_created) {
 
1279
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
 
1280
                             "child %" APR_PID_T_FMT " isn't taking over "
 
1281
                             "slots very quickly (%d of %d)",
 
1282
                             ap_my_pid, threads_created,
 
1283
                             ap_threads_per_child);
 
1284
            }
 
1285
            prev_threads_created = threads_created;
 
1286
        }
 
1287
    }
 
1288
 
 
1289
    /* What state should this child_main process be listed as in the
 
1290
     * scoreboard...?
 
1291
     *  ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
 
1292
     *                                      (request_rec *) NULL);
 
1293
     *
 
1294
     *  This state should be listed separately in the scoreboard, in some kind
 
1295
     *  of process_status, not mixed in with the worker threads' status.
 
1296
     *  "life_status" is almost right, but it's in the worker's structure, and
 
1297
     *  the name could be clearer.   gla
 
1298
     */
 
1299
    apr_thread_exit(thd, APR_SUCCESS);
 
1300
    return NULL;
 
1301
}
 
1302
 
 
1303
static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
 
1304
{
 
1305
    int i;
 
1306
    apr_status_t rv, thread_rv;
 
1307
 
 
1308
    if (listener) {
 
1309
        int iter;
 
1310
 
 
1311
        /* deal with a rare timing window which affects waking up the
 
1312
         * listener thread...  if the signal sent to the listener thread
 
1313
         * is delivered between the time it verifies that the
 
1314
         * listener_may_exit flag is clear and the time it enters a
 
1315
         * blocking syscall, the signal didn't do any good...  work around
 
1316
         * that by sleeping briefly and sending it again
 
1317
         */
 
1318
 
 
1319
        iter = 0;
 
1320
        while (iter < 10 &&
 
1321
#ifdef HAVE_PTHREAD_KILL
 
1322
               pthread_kill(*listener_os_thread, 0)
 
1323
#else
 
1324
               kill(ap_my_pid, 0)
 
1325
#endif
 
1326
               == 0) {
 
1327
            /* listener not dead yet */
 
1328
            apr_sleep(apr_time_make(0, 500000));
 
1329
            wakeup_listener();
 
1330
            ++iter;
 
1331
        }
 
1332
        if (iter >= 10) {
 
1333
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
 
1334
                         "the listener thread didn't exit");
 
1335
        }
 
1336
        else {
 
1337
            rv = apr_thread_join(&thread_rv, listener);
 
1338
            if (rv != APR_SUCCESS) {
 
1339
                ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
 
1340
                             "apr_thread_join: unable to join listener thread");
 
1341
            }
 
1342
        }
 
1343
    }
 
1344
 
 
1345
    for (i = 0; i < ap_threads_per_child; i++) {
 
1346
        if (threads[i]) {       /* if we ever created this thread */
 
1347
            rv = apr_thread_join(&thread_rv, threads[i]);
 
1348
            if (rv != APR_SUCCESS) {
 
1349
                ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
 
1350
                             "apr_thread_join: unable to join worker "
 
1351
                             "thread %d", i);
 
1352
            }
 
1353
        }
 
1354
    }
 
1355
}
 
1356
 
 
1357
static void join_start_thread(apr_thread_t * start_thread_id)
 
1358
{
 
1359
    apr_status_t rv, thread_rv;
 
1360
 
 
1361
    start_thread_may_exit = 1;  /* tell it to give up in case it is still
 
1362
                                 * trying to take over slots from a
 
1363
                                 * previous generation
 
1364
                                 */
 
1365
    rv = apr_thread_join(&thread_rv, start_thread_id);
 
1366
    if (rv != APR_SUCCESS) {
 
1367
        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
 
1368
                     "apr_thread_join: unable to join the start " "thread");
 
1369
    }
 
1370
}
 
1371
 
 
1372
static void child_main(int child_num_arg)
 
1373
{
 
1374
    apr_thread_t **threads;
 
1375
    apr_status_t rv;
 
1376
    thread_starter *ts;
 
1377
    apr_threadattr_t *thread_attr;
 
1378
    apr_thread_t *start_thread_id;
 
1379
 
 
1380
    mpm_state = AP_MPMQ_STARTING;       /* for benefit of any hooks that run as this
 
1381
                                         * child initializes
 
1382
                                         */
 
1383
    ap_my_pid = getpid();
 
1384
    ap_fatal_signal_child_setup(ap_server_conf);
 
1385
    apr_pool_create(&pchild, pconf);
 
1386
 
 
1387
    /*stuff to do before we switch id's, so we have permissions. */
 
1388
    ap_reopen_scoreboard(pchild, NULL, 0);
 
1389
 
 
1390
    if (unixd_setup_child()) {
 
1391
        clean_child_exit(APEXIT_CHILDFATAL);
 
1392
    }
 
1393
 
 
1394
    ap_run_child_init(pchild, ap_server_conf);
 
1395
 
 
1396
    /* done with init critical section */
 
1397
 
 
1398
    /* Just use the standard apr_setup_signal_thread to block all signals
 
1399
     * from being received.  The child processes no longer use signals for
 
1400
     * any communication with the parent process.
 
1401
     */
 
1402
    rv = apr_setup_signal_thread();
 
1403
    if (rv != APR_SUCCESS) {
 
1404
        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
 
1405
                     "Couldn't initialize signal thread");
 
1406
        clean_child_exit(APEXIT_CHILDFATAL);
 
1407
    }
 
1408
 
 
1409
    if (ap_max_requests_per_child) {
 
1410
        requests_this_child = ap_max_requests_per_child;
 
1411
    }
 
1412
    else {
 
1413
        /* coding a value of zero means infinity */
 
1414
        requests_this_child = INT_MAX;
 
1415
    }
 
1416
 
 
1417
    /* Setup worker threads */
 
1418
 
 
1419
    /* clear the storage; we may not create all our threads immediately,
 
1420
     * and we want a 0 entry to indicate a thread which was not created
 
1421
     */
 
1422
    threads = (apr_thread_t **) calloc(1,
 
1423
                                       sizeof(apr_thread_t *) *
 
1424
                                       ap_threads_per_child);
 
1425
    if (threads == NULL) {
 
1426
        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
 
1427
                     "malloc: out of memory");
 
1428
        clean_child_exit(APEXIT_CHILDFATAL);
 
1429
    }
 
1430
 
 
1431
    ts = (thread_starter *) apr_palloc(pchild, sizeof(*ts));
 
1432
 
 
1433
    apr_threadattr_create(&thread_attr, pchild);
 
1434
    /* 0 means PTHREAD_CREATE_JOINABLE */
 
1435
    apr_threadattr_detach_set(thread_attr, 0);
 
1436
 
 
1437
    if (ap_thread_stacksize != 0) {
 
1438
        apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
 
1439
    }
 
1440
 
 
1441
    ts->threads = threads;
 
1442
    ts->listener = NULL;
 
1443
    ts->child_num_arg = child_num_arg;
 
1444
    ts->threadattr = thread_attr;
 
1445
 
 
1446
    rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
 
1447
                           ts, pchild);
 
1448
    if (rv != APR_SUCCESS) {
 
1449
        ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
 
1450
                     "apr_thread_create: unable to create worker thread");
 
1451
        /* let the parent decide how bad this really is */
 
1452
        clean_child_exit(APEXIT_CHILDSICK);
 
1453
    }
 
1454
 
 
1455
    mpm_state = AP_MPMQ_RUNNING;
 
1456
 
 
1457
    /* If we are only running in one_process mode, we will want to
 
1458
     * still handle signals. */
 
1459
    if (one_process) {
 
1460
        /* Block until we get a terminating signal. */
 
1461
        apr_signal_thread(check_signal);
 
1462
        /* make sure the start thread has finished; signal_threads()
 
1463
         * and join_workers() depend on that
 
1464
         */
 
1465
        /* XXX join_start_thread() won't be awakened if one of our
 
1466
         *     threads encounters a critical error and attempts to
 
1467
         *     shutdown this child
 
1468
         */
 
1469
        join_start_thread(start_thread_id);
 
1470
 
 
1471
        /* helps us terminate a little more quickly than the dispatch of the
 
1472
         * signal thread; beats the Pipe of Death and the browsers
 
1473
         */
 
1474
        signal_threads(ST_UNGRACEFUL);
 
1475
 
 
1476
        /* A terminating signal was received. Now join each of the
 
1477
         * workers to clean them up.
 
1478
         *   If the worker already exited, then the join frees
 
1479
         *   their resources and returns.
 
1480
         *   If the worker hasn't exited, then this blocks until
 
1481
         *   they have (then cleans up).
 
1482
         */
 
1483
        join_workers(ts->listener, threads);
 
1484
    }
 
1485
    else {                      /* !one_process */
 
1486
        /* remove SIGTERM from the set of blocked signals...  if one of
 
1487
         * the other threads in the process needs to take us down
 
1488
         * (e.g., for MaxRequestsPerChild) it will send us SIGTERM
 
1489
         */
 
1490
        unblock_signal(SIGTERM);
 
1491
        apr_signal(SIGTERM, dummy_signal_handler);
 
1492
        /* Watch for any messages from the parent over the POD */
 
1493
        while (1) {
 
1494
            rv = ap_mpm_pod_check(pod);
 
1495
            if (rv == AP_NORESTART) {
 
1496
                /* see if termination was triggered while we slept */
 
1497
                switch (terminate_mode) {
 
1498
                case ST_GRACEFUL:
 
1499
                    rv = AP_GRACEFUL;
 
1500
                    break;
 
1501
                case ST_UNGRACEFUL:
 
1502
                    rv = AP_RESTART;
 
1503
                    break;
 
1504
                }
 
1505
            }
 
1506
            if (rv == AP_GRACEFUL || rv == AP_RESTART) {
 
1507
                /* make sure the start thread has finished;
 
1508
                 * signal_threads() and join_workers depend on that
 
1509
                 */
 
1510
                join_start_thread(start_thread_id);
 
1511
                signal_threads(rv ==
 
1512
                               AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
 
1513
                break;
 
1514
            }
 
1515
        }
 
1516
 
 
1517
        /* A terminating signal was received. Now join each of the
 
1518
         * workers to clean them up.
 
1519
         *   If the worker already exited, then the join frees
 
1520
         *   their resources and returns.
 
1521
         *   If the worker hasn't exited, then this blocks until
 
1522
         *   they have (then cleans up).
 
1523
         */
 
1524
        join_workers(ts->listener, threads);
 
1525
    }
 
1526
 
 
1527
    free(threads);
 
1528
 
 
1529
    clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
 
1530
}
 
1531
 
 
1532
static int make_child(server_rec * s, int slot)
 
1533
{
 
1534
    int pid;
 
1535
 
 
1536
    if (slot + 1 > ap_max_daemons_limit) {
 
1537
        ap_max_daemons_limit = slot + 1;
 
1538
    }
 
1539
 
 
1540
    if (one_process) {
 
1541
        set_signals();
 
1542
        ap_scoreboard_image->parent[slot].pid = getpid();
 
1543
        child_main(slot);
 
1544
    }
 
1545
 
 
1546
    if ((pid = fork()) == -1) {
 
1547
        ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
 
1548
                     "fork: Unable to fork new process");
 
1549
 
 
1550
        /* fork didn't succeed. Fix the scoreboard or else
 
1551
         * it will say SERVER_STARTING forever and ever
 
1552
         */
 
1553
        ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, NULL);
 
1554
 
 
1555
        /* In case system resources are maxxed out, we don't want
 
1556
           Apache running away with the CPU trying to fork over and
 
1557
           over and over again. */
 
1558
        apr_sleep(apr_time_from_sec(10));
 
1559
 
 
1560
        return -1;
 
1561
    }
 
1562
 
 
1563
    if (!pid) {
 
1564
#ifdef HAVE_BINDPROCESSOR
 
1565
        /* By default, AIX binds to a single processor.  This bit unbinds
 
1566
         * children which will then bind to another CPU.
 
1567
         */
 
1568
        int status = bindprocessor(BINDPROCESS, (int) getpid(),
 
1569
                                   PROCESSOR_CLASS_ANY);
 
1570
        if (status != OK)
 
1571
            ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
 
1572
                         ap_server_conf,
 
1573
                         "processor unbind failed %d", status);
 
1574
#endif
 
1575
        RAISE_SIGSTOP(MAKE_CHILD);
 
1576
 
 
1577
        apr_signal(SIGTERM, just_die);
 
1578
        child_main(slot);
 
1579
 
 
1580
        clean_child_exit(0);
 
1581
    }
 
1582
    /* else */
 
1583
    ap_scoreboard_image->parent[slot].quiescing = 0;
 
1584
    ap_scoreboard_image->parent[slot].pid = pid;
 
1585
    return 0;
 
1586
}
 
1587
 
 
1588
/* start up a bunch of children */
 
1589
static void startup_children(int number_to_start)
 
1590
{
 
1591
    int i;
 
1592
 
 
1593
    for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
 
1594
        if (ap_scoreboard_image->parent[i].pid != 0) {
 
1595
            continue;
 
1596
        }
 
1597
        if (make_child(ap_server_conf, i) < 0) {
 
1598
            break;
 
1599
        }
 
1600
        --number_to_start;
 
1601
    }
 
1602
}
 
1603
 
 
1604
 
 
1605
/*
 
1606
 * idle_spawn_rate is the number of children that will be spawned on the
 
1607
 * next maintenance cycle if there aren't enough idle servers.  It is
 
1608
 * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
 
1609
 * without the need to spawn.
 
1610
 */
 
1611
static int idle_spawn_rate = 1;
 
1612
#ifndef MAX_SPAWN_RATE
 
1613
#define MAX_SPAWN_RATE        (32)
 
1614
#endif
 
1615
static int hold_off_on_exponential_spawning;
 
1616
 
 
1617
static void perform_idle_server_maintenance(void)
 
1618
{
 
1619
    int i, j;
 
1620
    int idle_thread_count;
 
1621
    worker_score *ws;
 
1622
    process_score *ps;
 
1623
    int free_length;
 
1624
    int totally_free_length = 0;
 
1625
    int free_slots[MAX_SPAWN_RATE];
 
1626
    int last_non_dead;
 
1627
    int total_non_dead;
 
1628
    int active_thread_count = 0;
 
1629
 
 
1630
    /* initialize the free_list */
 
1631
    free_length = 0;
 
1632
 
 
1633
    idle_thread_count = 0;
 
1634
    last_non_dead = -1;
 
1635
    total_non_dead = 0;
 
1636
 
 
1637
    for (i = 0; i < ap_daemons_limit; ++i) {
 
1638
        /* Initialization to satisfy the compiler. It doesn't know
 
1639
         * that ap_threads_per_child is always > 0 */
 
1640
        int status = SERVER_DEAD;
 
1641
        int any_dying_threads = 0;
 
1642
        int any_dead_threads = 0;
 
1643
        int all_dead_threads = 1;
 
1644
 
 
1645
        if (i >= ap_max_daemons_limit
 
1646
            && totally_free_length == idle_spawn_rate)
 
1647
            break;
 
1648
        ps = &ap_scoreboard_image->parent[i];
 
1649
        for (j = 0; j < ap_threads_per_child; j++) {
 
1650
            ws = &ap_scoreboard_image->servers[i][j];
 
1651
            status = ws->status;
 
1652
 
 
1653
            /* XXX any_dying_threads is probably no longer needed    GLA */
 
1654
            any_dying_threads = any_dying_threads ||
 
1655
                (status == SERVER_GRACEFUL);
 
1656
            any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
 
1657
            all_dead_threads = all_dead_threads &&
 
1658
                (status == SERVER_DEAD || status == SERVER_GRACEFUL);
 
1659
 
 
1660
            /* We consider a starting server as idle because we started it
 
1661
             * at least a cycle ago, and if it still hasn't finished starting
 
1662
             * then we're just going to swamp things worse by forking more.
 
1663
             * So we hopefully won't need to fork more if we count it.
 
1664
             * This depends on the ordering of SERVER_READY and SERVER_STARTING.
 
1665
             */
 
1666
            if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
 
1667
                                   for loop if no pid?  not much else matters */
 
1668
                if (status <= SERVER_READY &&
 
1669
                        !ps->quiescing && ps->generation == ap_my_generation) {
 
1670
                    ++idle_thread_count;
 
1671
                }
 
1672
                if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
 
1673
                    ++active_thread_count;
 
1674
                }
 
1675
            }
 
1676
        }
 
1677
        if (any_dead_threads
 
1678
            && totally_free_length < idle_spawn_rate
 
1679
            && free_length < MAX_SPAWN_RATE
 
1680
            && (!ps->pid      /* no process in the slot */
 
1681
                  || ps->quiescing)) {  /* or at least one is going away */
 
1682
            if (all_dead_threads) {
 
1683
                /* great! we prefer these, because the new process can
 
1684
                 * start more threads sooner.  So prioritize this slot
 
1685
                 * by putting it ahead of any slots with active threads.
 
1686
                 *
 
1687
                 * first, make room by moving a slot that's potentially still
 
1688
                 * in use to the end of the array
 
1689
                 */
 
1690
                free_slots[free_length] = free_slots[totally_free_length];
 
1691
                free_slots[totally_free_length++] = i;
 
1692
            }
 
1693
            else {
 
1694
                /* slot is still in use - back of the bus
 
1695
                 */
 
1696
                free_slots[free_length] = i;
 
1697
            }
 
1698
            ++free_length;
 
1699
        }
 
1700
        /* XXX if (!ps->quiescing)     is probably more reliable  GLA */
 
1701
        if (!any_dying_threads) {
 
1702
            last_non_dead = i;
 
1703
            ++total_non_dead;
 
1704
        }
 
1705
    }
 
1706
 
 
1707
    if (sick_child_detected) {
 
1708
        if (active_thread_count > 0) {
 
1709
            /* some child processes appear to be working.  don't kill the
 
1710
             * whole server.
 
1711
             */
 
1712
            sick_child_detected = 0;
 
1713
        }
 
1714
        else {
 
1715
            /* looks like a basket case.  give up.
 
1716
             */
 
1717
            shutdown_pending = 1;
 
1718
            child_fatal = 1;
 
1719
            ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
 
1720
                         ap_server_conf,
 
1721
                         "No active workers found..."
 
1722
                         " Apache is exiting!");
 
1723
            /* the child already logged the failure details */
 
1724
            return;
 
1725
        }
 
1726
    }
 
1727
 
 
1728
    ap_max_daemons_limit = last_non_dead + 1;
 
1729
 
 
1730
    if (idle_thread_count > max_spare_threads) {
 
1731
        /* Kill off one child */
 
1732
        ap_mpm_pod_signal(pod, TRUE);
 
1733
        idle_spawn_rate = 1;
 
1734
    }
 
1735
    else if (idle_thread_count < min_spare_threads) {
 
1736
        /* terminate the free list */
 
1737
        if (free_length == 0) {
 
1738
            /* only report this condition once */
 
1739
            static int reported = 0;
 
1740
 
 
1741
            if (!reported) {
 
1742
                ap_log_error(APLOG_MARK, APLOG_ERR, 0,
 
1743
                             ap_server_conf,
 
1744
                             "server reached MaxClients setting, consider"
 
1745
                             " raising the MaxClients setting");
 
1746
                reported = 1;
 
1747
            }
 
1748
            idle_spawn_rate = 1;
 
1749
        }
 
1750
        else {
 
1751
            if (free_length > idle_spawn_rate) {
 
1752
                free_length = idle_spawn_rate;
 
1753
            }
 
1754
            if (idle_spawn_rate >= 8) {
 
1755
                ap_log_error(APLOG_MARK, APLOG_INFO, 0,
 
1756
                             ap_server_conf,
 
1757
                             "server seems busy, (you may need "
 
1758
                             "to increase StartServers, ThreadsPerChild "
 
1759
                             "or Min/MaxSpareThreads), "
 
1760
                             "spawning %d children, there are around %d idle "
 
1761
                             "threads, and %d total children", free_length,
 
1762
                             idle_thread_count, total_non_dead);
 
1763
            }
 
1764
            for (i = 0; i < free_length; ++i) {
 
1765
                make_child(ap_server_conf, free_slots[i]);
 
1766
            }
 
1767
            /* the next time around we want to spawn twice as many if this
 
1768
             * wasn't good enough, but not if we've just done a graceful
 
1769
             */
 
1770
            if (hold_off_on_exponential_spawning) {
 
1771
                --hold_off_on_exponential_spawning;
 
1772
            }
 
1773
            else if (idle_spawn_rate < MAX_SPAWN_RATE) {
 
1774
                idle_spawn_rate *= 2;
 
1775
            }
 
1776
        }
 
1777
    }
 
1778
    else {
 
1779
        idle_spawn_rate = 1;
 
1780
    }
 
1781
}
 
1782
 
 
1783
static void server_main_loop(int remaining_children_to_start)
 
1784
{
 
1785
    int child_slot;
 
1786
    apr_exit_why_e exitwhy;
 
1787
    int status, processed_status;
 
1788
    apr_proc_t pid;
 
1789
    int i;
 
1790
 
 
1791
    while (!restart_pending && !shutdown_pending) {
 
1792
        ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
 
1793
 
 
1794
        if (pid.pid != -1) {
 
1795
            processed_status = ap_process_child_status(&pid, exitwhy, status);
 
1796
            if (processed_status == APEXIT_CHILDFATAL) {
 
1797
                shutdown_pending = 1;
 
1798
                child_fatal = 1;
 
1799
                return;
 
1800
            }
 
1801
            else if (processed_status == APEXIT_CHILDSICK) {
 
1802
                /* tell perform_idle_server_maintenance to check into this
 
1803
                 * on the next timer pop
 
1804
                 */
 
1805
                sick_child_detected = 1;
 
1806
            }
 
1807
            /* non-fatal death... note that it's gone in the scoreboard. */
 
1808
            child_slot = find_child_by_pid(&pid);
 
1809
            if (child_slot >= 0) {
 
1810
                for (i = 0; i < ap_threads_per_child; i++)
 
1811
                    ap_update_child_status_from_indexes(child_slot, i,
 
1812
                                                        SERVER_DEAD,
 
1813
                                                        (request_rec *) NULL);
 
1814
 
 
1815
                ap_scoreboard_image->parent[child_slot].pid = 0;
 
1816
                ap_scoreboard_image->parent[child_slot].quiescing = 0;
 
1817
                if (processed_status == APEXIT_CHILDSICK) {
 
1818
                    /* resource shortage, minimize the fork rate */
 
1819
                    idle_spawn_rate = 1;
 
1820
                }
 
1821
                else if (remaining_children_to_start
 
1822
                         && child_slot < ap_daemons_limit) {
 
1823
                    /* we're still doing a 1-for-1 replacement of dead
 
1824
                     * children with new children
 
1825
                     */
 
1826
                    make_child(ap_server_conf, child_slot);
 
1827
                    --remaining_children_to_start;
 
1828
                }
 
1829
#if APR_HAS_OTHER_CHILD
 
1830
            }
 
1831
            else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
 
1832
                                                status) == 0) {
 
1833
                /* handled */
 
1834
#endif
 
1835
            }
 
1836
            else if (is_graceful) {
 
1837
                /* Great, we've probably just lost a slot in the
 
1838
                 * scoreboard.  Somehow we don't know about this child.
 
1839
                 */
 
1840
                ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
 
1841
                             ap_server_conf,
 
1842
                             "long lost child came home! (pid %ld)",
 
1843
                             (long) pid.pid);
 
1844
            }
 
1845
            /* Don't perform idle maintenance when a child dies,
 
1846
             * only do it when there's a timeout.  Remember only a
 
1847
             * finite number of children can die, and it's pretty
 
1848
             * pathological for a lot to die suddenly.
 
1849
             */
 
1850
            continue;
 
1851
        }
 
1852
        else if (remaining_children_to_start) {
 
1853
            /* we hit a 1 second timeout in which none of the previous
 
1854
             * generation of children needed to be reaped... so assume
 
1855
             * they're all done, and pick up the slack if any is left.
 
1856
             */
 
1857
            startup_children(remaining_children_to_start);
 
1858
            remaining_children_to_start = 0;
 
1859
            /* In any event we really shouldn't do the code below because
 
1860
             * few of the servers we just started are in the IDLE state
 
1861
             * yet, so we'd mistakenly create an extra server.
 
1862
             */
 
1863
            continue;
 
1864
        }
 
1865
 
 
1866
        perform_idle_server_maintenance();
 
1867
    }
 
1868
}
 
1869
 
 
1870
int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
 
1871
{
 
1872
    int remaining_children_to_start;
 
1873
 
 
1874
    ap_log_pid(pconf, ap_pid_fname);
 
1875
 
 
1876
    first_server_limit = server_limit;
 
1877
    first_thread_limit = thread_limit;
 
1878
 
 
1879
    if (changed_limit_at_restart) {
 
1880
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
 
1881
                     "WARNING: Attempt to change ServerLimit or ThreadLimit "
 
1882
                     "ignored during restart");
 
1883
        changed_limit_at_restart = 0;
 
1884
    }
 
1885
 
 
1886
    if (!is_graceful) {
 
1887
        if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
 
1888
            mpm_state = AP_MPMQ_STOPPING;
 
1889
            return 1;
 
1890
        }
 
1891
        /* fix the generation number in the global score; we just got a new,
 
1892
         * cleared scoreboard
 
1893
         */
 
1894
        ap_scoreboard_image->global->running_generation = ap_my_generation;
 
1895
    }
 
1896
 
 
1897
    set_signals();
 
1898
    /* Don't thrash... */
 
1899
    if (max_spare_threads < min_spare_threads + ap_threads_per_child)
 
1900
        max_spare_threads = min_spare_threads + ap_threads_per_child;
 
1901
 
 
1902
    /* If we're doing a graceful_restart then we're going to see a lot
 
1903
     * of children exiting immediately when we get into the main loop
 
1904
     * below (because we just sent them AP_SIG_GRACEFUL).  This happens pretty
 
1905
     * rapidly... and for each one that exits we'll start a new one until
 
1906
     * we reach at least daemons_min_free.  But we may be permitted to
 
1907
     * start more than that, so we'll just keep track of how many we're
 
1908
     * supposed to start up without the 1 second penalty between each fork.
 
1909
     */
 
1910
    remaining_children_to_start = ap_daemons_to_start;
 
1911
    if (remaining_children_to_start > ap_daemons_limit) {
 
1912
        remaining_children_to_start = ap_daemons_limit;
 
1913
    }
 
1914
    if (!is_graceful) {
 
1915
        startup_children(remaining_children_to_start);
 
1916
        remaining_children_to_start = 0;
 
1917
    }
 
1918
    else {
 
1919
        /* give the system some time to recover before kicking into
 
1920
         * exponential mode */
 
1921
        hold_off_on_exponential_spawning = 10;
 
1922
    }
 
1923
 
 
1924
    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
 
1925
                 "%s configured -- resuming normal operations",
 
1926
                 ap_get_server_version());
 
1927
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
 
1928
                 "Server built: %s", ap_get_server_built());
 
1929
 
 
1930
    restart_pending = shutdown_pending = 0;
 
1931
    mpm_state = AP_MPMQ_RUNNING;
 
1932
 
 
1933
    server_main_loop(remaining_children_to_start);
 
1934
    mpm_state = AP_MPMQ_STOPPING;
 
1935
 
 
1936
    if (shutdown_pending && !is_graceful) {
 
1937
        /* Time to shut down:
 
1938
         * Kill child processes, tell them to call child_exit, etc...
 
1939
         */
 
1940
        ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
 
1941
        ap_reclaim_child_processes(1);  /* Start with SIGTERM */
 
1942
 
 
1943
        if (!child_fatal) {
 
1944
            /* cleanup pid file on normal shutdown */
 
1945
            const char *pidfile = NULL;
 
1946
            pidfile = ap_server_root_relative(pconf, ap_pid_fname);
 
1947
            if (pidfile != NULL && unlink(pidfile) == 0)
 
1948
                ap_log_error(APLOG_MARK, APLOG_INFO, 0,
 
1949
                             ap_server_conf,
 
1950
                             "removed PID file %s (pid=%ld)",
 
1951
                             pidfile, (long) getpid());
 
1952
 
 
1953
            ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
 
1954
                         ap_server_conf, "caught SIGTERM, shutting down");
 
1955
        }
 
1956
        return 1;
 
1957
    } else if (shutdown_pending) {
 
1958
        /* Time to gracefully shut down:
 
1959
         * Kill child processes, tell them to call child_exit, etc...
 
1960
         */
 
1961
        int active_children;
 
1962
        int index;
 
1963
        apr_time_t cutoff = 0;
 
1964
 
 
1965
        /* Close our listeners, and then ask our children to do same */
 
1966
        ap_close_listeners();
 
1967
        ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
 
1968
        ap_relieve_child_processes();
 
1969
 
 
1970
        if (!child_fatal) {
 
1971
            /* cleanup pid file on normal shutdown */
 
1972
            const char *pidfile = NULL;
 
1973
            pidfile = ap_server_root_relative (pconf, ap_pid_fname);
 
1974
            if ( pidfile != NULL && unlink(pidfile) == 0)
 
1975
                ap_log_error(APLOG_MARK, APLOG_INFO, 0,
 
1976
                             ap_server_conf,
 
1977
                             "removed PID file %s (pid=%ld)",
 
1978
                             pidfile, (long)getpid());
 
1979
 
 
1980
            ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
 
1981
                         "caught " AP_SIG_GRACEFUL_STOP_STRING
 
1982
                         ", shutting down gracefully");
 
1983
        }
 
1984
 
 
1985
        if (ap_graceful_shutdown_timeout) {
 
1986
            cutoff = apr_time_now() +
 
1987
                     apr_time_from_sec(ap_graceful_shutdown_timeout);
 
1988
        }
 
1989
 
 
1990
        /* Don't really exit until each child has finished */
 
1991
        shutdown_pending = 0;
 
1992
        do {
 
1993
            /* Pause for a second */
 
1994
            apr_sleep(apr_time_from_sec(1));
 
1995
 
 
1996
            /* Relieve any children which have now exited */
 
1997
            ap_relieve_child_processes();
 
1998
 
 
1999
            active_children = 0;
 
2000
            for (index = 0; index < ap_daemons_limit; ++index) {
 
2001
                if (MPM_CHILD_PID(index) != 0) {
 
2002
                    if (kill(MPM_CHILD_PID(index), 0) == 0) {
 
2003
                            active_children = 1;
 
2004
                            /* Having just one child is enough to stay around */
 
2005
                            break;
 
2006
                    }
 
2007
                }
 
2008
            }
 
2009
        } while (!shutdown_pending && active_children &&
 
2010
                 (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
 
2011
 
 
2012
        /* We might be here because we received SIGTERM, either
 
2013
         * way, try and make sure that all of our processes are
 
2014
         * really dead.
 
2015
         */
 
2016
        ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
 
2017
        ap_reclaim_child_processes(1);
 
2018
 
 
2019
        return 1;
 
2020
    }
 
2021
 
 
2022
    /* we've been told to restart */
 
2023
    apr_signal(SIGHUP, SIG_IGN);
 
2024
 
 
2025
    if (one_process) {
 
2026
        /* not worth thinking about */
 
2027
        return 1;
 
2028
    }
 
2029
 
 
2030
    /* advance to the next generation */
 
2031
    /* XXX: we really need to make sure this new generation number isn't in
 
2032
     * use by any of the children.
 
2033
     */
 
2034
    ++ap_my_generation;
 
2035
    ap_scoreboard_image->global->running_generation = ap_my_generation;
 
2036
 
 
2037
    if (is_graceful) {
 
2038
        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
 
2039
                     AP_SIG_GRACEFUL_STRING
 
2040
                     " received.  Doing graceful restart");
 
2041
        /* wake up the children...time to die.  But we'll have more soon */
 
2042
        ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
 
2043
 
 
2044
 
 
2045
        /* This is mostly for debugging... so that we know what is still
 
2046
         * gracefully dealing with existing request.
 
2047
         */
 
2048
 
 
2049
    }
 
2050
    else {
 
2051
        /* Kill 'em all.  Since the child acts the same on the parents SIGTERM
 
2052
         * and a SIGHUP, we may as well use the same signal, because some user
 
2053
         * pthreads are stealing signals from us left and right.
 
2054
         */
 
2055
        ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
 
2056
 
 
2057
        ap_reclaim_child_processes(1);  /* Start with SIGTERM */
 
2058
        ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
 
2059
                     "SIGHUP received.  Attempting to restart");
 
2060
    }
 
2061
 
 
2062
    return 0;
 
2063
}
 
2064
 
 
2065
/* This really should be a post_config hook, but the error log is already
 
2066
 * redirected by that point, so we need to do this in the open_logs phase.
 
2067
 */
 
2068
static int worker_open_logs(apr_pool_t * p, apr_pool_t * plog,
 
2069
                            apr_pool_t * ptemp, server_rec * s)
 
2070
{
 
2071
    apr_status_t rv;
 
2072
 
 
2073
    pconf = p;
 
2074
    ap_server_conf = s;
 
2075
 
 
2076
    if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
 
2077
        ap_log_error(APLOG_MARK, APLOG_ALERT | APLOG_STARTUP, 0,
 
2078
                     NULL, "no listening sockets available, shutting down");
 
2079
        return DONE;
 
2080
    }
 
2081
 
 
2082
    if (!one_process) {
 
2083
        if ((rv = ap_mpm_pod_open(pconf, &pod))) {
 
2084
            ap_log_error(APLOG_MARK, APLOG_CRIT | APLOG_STARTUP, rv, NULL,
 
2085
                         "Could not open pipe-of-death.");
 
2086
            return DONE;
 
2087
        }
 
2088
    }
 
2089
    return OK;
 
2090
}
 
2091
 
 
2092
static int worker_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
 
2093
                             apr_pool_t * ptemp)
 
2094
{
 
2095
    static int restart_num = 0;
 
2096
    int no_detach, debug, foreground;
 
2097
    ap_directive_t *pdir;
 
2098
    ap_directive_t *max_clients = NULL;
 
2099
    apr_status_t rv;
 
2100
 
 
2101
    mpm_state = AP_MPMQ_STARTING;
 
2102
 
 
2103
    /* make sure that "ThreadsPerChild" gets set before "MaxClients" */
 
2104
    for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
 
2105
        if (strncasecmp(pdir->directive, "ThreadsPerChild", 15) == 0) {
 
2106
            if (!max_clients) {
 
2107
                /* we're in the clear, got ThreadsPerChild first */
 
2108
                break;
 
2109
            }
 
2110
            else {
 
2111
                /* now to swap the data */
 
2112
                ap_directive_t temp;
 
2113
 
 
2114
                temp.directive = pdir->directive;
 
2115
                temp.args = pdir->args;
 
2116
                /* Make sure you don't change 'next', or you may get loops! */
 
2117
                /* XXX: first_child, parent, and data can never be set
 
2118
                 * for these directives, right? -aaron */
 
2119
                temp.filename = pdir->filename;
 
2120
                temp.line_num = pdir->line_num;
 
2121
 
 
2122
                pdir->directive = max_clients->directive;
 
2123
                pdir->args = max_clients->args;
 
2124
                pdir->filename = max_clients->filename;
 
2125
                pdir->line_num = max_clients->line_num;
 
2126
 
 
2127
                max_clients->directive = temp.directive;
 
2128
                max_clients->args = temp.args;
 
2129
                max_clients->filename = temp.filename;
 
2130
                max_clients->line_num = temp.line_num;
 
2131
                break;
 
2132
            }
 
2133
        }
 
2134
        else if (!max_clients
 
2135
                 && strncasecmp(pdir->directive, "MaxClients", 10) == 0) {
 
2136
            max_clients = pdir;
 
2137
        }
 
2138
    }
 
2139
 
 
2140
    debug = ap_exists_config_define("DEBUG");
 
2141
 
 
2142
    if (debug) {
 
2143
        foreground = one_process = 1;
 
2144
        no_detach = 0;
 
2145
    }
 
2146
    else {
 
2147
        one_process = ap_exists_config_define("ONE_PROCESS");
 
2148
        no_detach = ap_exists_config_define("NO_DETACH");
 
2149
        foreground = ap_exists_config_define("FOREGROUND");
 
2150
    }
 
2151
 
 
2152
    /* sigh, want this only the second time around */
 
2153
    if (restart_num++ == 1) {
 
2154
        is_graceful = 0;
 
2155
        rv = apr_pollset_create(&event_pollset, 1, plog,
 
2156
                                APR_POLLSET_THREADSAFE);
 
2157
        if (rv != APR_SUCCESS) {
 
2158
            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
 
2159
                         "Couldn't create a Thread Safe Pollset. "
 
2160
                         "Is it supported on your platform?");
 
2161
            return HTTP_INTERNAL_SERVER_ERROR;
 
2162
        }
 
2163
        apr_pollset_destroy(event_pollset);
 
2164
 
 
2165
        if (!one_process && !foreground) {
 
2166
            rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
 
2167
                                 : APR_PROC_DETACH_DAEMONIZE);
 
2168
            if (rv != APR_SUCCESS) {
 
2169
                ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
 
2170
                             "apr_proc_detach failed");
 
2171
                return HTTP_INTERNAL_SERVER_ERROR;
 
2172
            }
 
2173
        }
 
2174
        parent_pid = ap_my_pid = getpid();
 
2175
    }
 
2176
 
 
2177
    unixd_pre_config(ptemp);
 
2178
    ap_listen_pre_config();
 
2179
    ap_daemons_to_start = DEFAULT_START_DAEMON;
 
2180
    min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
 
2181
    max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
 
2182
    ap_daemons_limit = server_limit;
 
2183
    ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
 
2184
    ap_pid_fname = DEFAULT_PIDLOG;
 
2185
    ap_lock_fname = DEFAULT_LOCKFILE;
 
2186
    ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
 
2187
    ap_extended_status = 0;
 
2188
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
 
2189
    ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
 
2190
#endif
 
2191
 
 
2192
    apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
 
2193
 
 
2194
    return OK;
 
2195
}
 
2196
 
 
2197
static void event_hooks(apr_pool_t * p)
 
2198
{
 
2199
    /* The worker open_logs phase must run before the core's, or stderr
 
2200
     * will be redirected to a file, and the messages won't print to the
 
2201
     * console.
 
2202
     */
 
2203
    static const char *const aszSucc[] = { "core.c", NULL };
 
2204
    one_process = 0;
 
2205
 
 
2206
    ap_hook_open_logs(worker_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
 
2207
    /* we need to set the MPM state before other pre-config hooks use MPM query
 
2208
     * to retrieve it, so register as REALLY_FIRST
 
2209
     */
 
2210
    ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
 
2211
}
 
2212
 
 
2213
static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
 
2214
                                        const char *arg)
 
2215
{
 
2216
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2217
    if (err != NULL) {
 
2218
        return err;
 
2219
    }
 
2220
 
 
2221
    ap_daemons_to_start = atoi(arg);
 
2222
    return NULL;
 
2223
}
 
2224
 
 
2225
static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
 
2226
                                         const char *arg)
 
2227
{
 
2228
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2229
    if (err != NULL) {
 
2230
        return err;
 
2231
    }
 
2232
 
 
2233
    min_spare_threads = atoi(arg);
 
2234
    if (min_spare_threads <= 0) {
 
2235
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2236
                     "WARNING: detected MinSpareThreads set to non-positive.");
 
2237
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2238
                     "Resetting to 1 to avoid almost certain Apache failure.");
 
2239
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2240
                     "Please read the documentation.");
 
2241
        min_spare_threads = 1;
 
2242
    }
 
2243
 
 
2244
    return NULL;
 
2245
}
 
2246
 
 
2247
static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
 
2248
                                         const char *arg)
 
2249
{
 
2250
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2251
    if (err != NULL) {
 
2252
        return err;
 
2253
    }
 
2254
 
 
2255
    max_spare_threads = atoi(arg);
 
2256
    return NULL;
 
2257
}
 
2258
 
 
2259
static const char *set_max_clients(cmd_parms * cmd, void *dummy,
 
2260
                                   const char *arg)
 
2261
{
 
2262
    int max_clients;
 
2263
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2264
    if (err != NULL) {
 
2265
        return err;
 
2266
    }
 
2267
 
 
2268
    /* It is ok to use ap_threads_per_child here because we are
 
2269
     * sure that it gets set before MaxClients in the pre_config stage. */
 
2270
    max_clients = atoi(arg);
 
2271
    if (max_clients < ap_threads_per_child) {
 
2272
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2273
                     "WARNING: MaxClients (%d) must be at least as large",
 
2274
                     max_clients);
 
2275
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2276
                     " as ThreadsPerChild (%d). Automatically",
 
2277
                     ap_threads_per_child);
 
2278
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2279
                     " increasing MaxClients to %d.", ap_threads_per_child);
 
2280
        max_clients = ap_threads_per_child;
 
2281
    }
 
2282
    ap_daemons_limit = max_clients / ap_threads_per_child;
 
2283
    if ((max_clients > 0) && (max_clients % ap_threads_per_child)) {
 
2284
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2285
                     "WARNING: MaxClients (%d) is not an integer multiple",
 
2286
                     max_clients);
 
2287
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2288
                     " of ThreadsPerChild (%d), lowering MaxClients to %d",
 
2289
                     ap_threads_per_child,
 
2290
                     ap_daemons_limit * ap_threads_per_child);
 
2291
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2292
                     " for a maximum of %d child processes,",
 
2293
                     ap_daemons_limit);
 
2294
        max_clients = ap_daemons_limit * ap_threads_per_child;
 
2295
    }
 
2296
    if (ap_daemons_limit > server_limit) {
 
2297
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2298
                    "WARNING: MaxClients of %d would require %d servers,",
 
2299
                    max_clients, ap_daemons_limit);
 
2300
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2301
                    " and would exceed the ServerLimit value of %d.",
 
2302
                    server_limit);
 
2303
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2304
                    " Automatically lowering MaxClients to %d.  To increase,",
 
2305
                    server_limit * ap_threads_per_child);
 
2306
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2307
                    " please see the ServerLimit directive.");
 
2308
       ap_daemons_limit = server_limit;
 
2309
    }
 
2310
    else if (ap_daemons_limit < 1) {
 
2311
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2312
                     "WARNING: Require MaxClients > 0, setting to 1");
 
2313
        ap_daemons_limit = 1;
 
2314
    }
 
2315
    return NULL;
 
2316
}
 
2317
 
 
2318
static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
 
2319
                                         const char *arg)
 
2320
{
 
2321
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2322
    if (err != NULL) {
 
2323
        return err;
 
2324
    }
 
2325
 
 
2326
    ap_threads_per_child = atoi(arg);
 
2327
    if (ap_threads_per_child > thread_limit) {
 
2328
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2329
                     "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
 
2330
                     "value of %d", ap_threads_per_child, thread_limit);
 
2331
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2332
                     "threads, lowering ThreadsPerChild to %d. To increase, "
 
2333
                     "please see the", thread_limit);
 
2334
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2335
                     " ThreadLimit directive.");
 
2336
        ap_threads_per_child = thread_limit;
 
2337
    }
 
2338
    else if (ap_threads_per_child < 1) {
 
2339
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2340
                     "WARNING: Require ThreadsPerChild > 0, setting to 1");
 
2341
        ap_threads_per_child = 1;
 
2342
    }
 
2343
    return NULL;
 
2344
}
 
2345
static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
 
2346
{
 
2347
    int tmp_server_limit;
 
2348
 
 
2349
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2350
    if (err != NULL) {
 
2351
        return err;
 
2352
    }
 
2353
 
 
2354
    tmp_server_limit = atoi(arg);
 
2355
    /* you cannot change ServerLimit across a restart; ignore
 
2356
     * any such attempts
 
2357
     */
 
2358
    if (first_server_limit &&
 
2359
        tmp_server_limit != server_limit) {
 
2360
        /* how do we log a message?  the error log is a bit bucket at this
 
2361
         * point; we'll just have to set a flag so that ap_mpm_run()
 
2362
         * logs a warning later
 
2363
         */
 
2364
        changed_limit_at_restart = 1;
 
2365
        return NULL;
 
2366
    }
 
2367
    server_limit = tmp_server_limit;
 
2368
 
 
2369
    if (server_limit > MAX_SERVER_LIMIT) {
 
2370
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2371
                    "WARNING: ServerLimit of %d exceeds compile time limit "
 
2372
                    "of %d servers,", server_limit, MAX_SERVER_LIMIT);
 
2373
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2374
                    " lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
 
2375
       server_limit = MAX_SERVER_LIMIT;
 
2376
    }
 
2377
    else if (server_limit < 1) {
 
2378
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2379
                     "WARNING: Require ServerLimit > 0, setting to 1");
 
2380
        server_limit = 1;
 
2381
    }
 
2382
    return NULL;
 
2383
}
 
2384
 
 
2385
static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
 
2386
                                    const char *arg)
 
2387
{
 
2388
    int tmp_thread_limit;
 
2389
 
 
2390
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 
2391
    if (err != NULL) {
 
2392
        return err;
 
2393
    }
 
2394
 
 
2395
    tmp_thread_limit = atoi(arg);
 
2396
    /* you cannot change ThreadLimit across a restart; ignore
 
2397
     * any such attempts
 
2398
     */
 
2399
    if (first_thread_limit && tmp_thread_limit != thread_limit) {
 
2400
        /* how do we log a message?  the error log is a bit bucket at this
 
2401
         * point; we'll just have to set a flag so that ap_mpm_run()
 
2402
         * logs a warning later
 
2403
         */
 
2404
        changed_limit_at_restart = 1;
 
2405
        return NULL;
 
2406
    }
 
2407
    thread_limit = tmp_thread_limit;
 
2408
 
 
2409
    if (thread_limit > MAX_THREAD_LIMIT) {
 
2410
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2411
                     "WARNING: ThreadLimit of %d exceeds compile time limit "
 
2412
                     "of %d servers,", thread_limit, MAX_THREAD_LIMIT);
 
2413
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2414
                     " lowering ThreadLimit to %d.", MAX_THREAD_LIMIT);
 
2415
        thread_limit = MAX_THREAD_LIMIT;
 
2416
    }
 
2417
    else if (thread_limit < 1) {
 
2418
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
2419
                     "WARNING: Require ThreadLimit > 0, setting to 1");
 
2420
        thread_limit = 1;
 
2421
    }
 
2422
    return NULL;
 
2423
}
 
2424
 
 
2425
static const command_rec event_cmds[] = {
 
2426
    UNIX_DAEMON_COMMANDS,
 
2427
    LISTEN_COMMANDS,
 
2428
    AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
 
2429
                  "Number of child processes launched at server startup"),
 
2430
    AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
 
2431
                  "Maximum number of child processes for this run of Apache"),
 
2432
    AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
 
2433
                  "Minimum number of idle threads, to handle request spikes"),
 
2434
    AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
 
2435
                  "Maximum number of idle threads"),
 
2436
    AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
 
2437
                  "Maximum number of threads alive at the same time"),
 
2438
    AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
 
2439
                  "Number of threads each child creates"),
 
2440
    AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
 
2441
                  "Maximum number of worker threads per child process for this "
 
2442
                  "run of Apache - Upper limit for ThreadsPerChild"),
 
2443
    AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
 
2444
    {NULL}
 
2445
};
 
2446
 
 
2447
module AP_MODULE_DECLARE_DATA mpm_event_module = {
 
2448
    MPM20_MODULE_STUFF,
 
2449
    ap_mpm_rewrite_args,        /* hook to run before apache parses args */
 
2450
    NULL,                       /* create per-directory config structure */
 
2451
    NULL,                       /* merge per-directory config structures */
 
2452
    NULL,                       /* create per-server config structure */
 
2453
    NULL,                       /* merge per-server config structures */
 
2454
    event_cmds,                 /* command apr_table_t */
 
2455
    event_hooks                 /* register_hooks */
 
2456
};