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

« back to all changes in this revision

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