Apache HTTPD
event.c
Go to the documentation of this file.
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
47#include "apr.h"
48#include "apr_portable.h"
49#include "apr_strings.h"
50#include "apr_file_io.h"
51#include "apr_thread_proc.h"
52#include "apr_signal.h"
53#include "apr_thread_mutex.h"
54#include "apr_poll.h"
55#include "apr_ring.h"
56#include "apr_queue.h"
57#include "apr_atomic.h"
58#define APR_WANT_STRFUNC
59#include "apr_want.h"
60#include "apr_version.h"
61
62#include <stdlib.h>
63
64#if APR_HAVE_UNISTD_H
65#include <unistd.h>
66#endif
67#if APR_HAVE_SYS_SOCKET_H
68#include <sys/socket.h>
69#endif
70#if APR_HAVE_SYS_WAIT_H
71#include <sys/wait.h>
72#endif
73#ifdef HAVE_SYS_PROCESSOR_H
74#include <sys/processor.h> /* for bindprocessor() */
75#endif
76
77#if !APR_HAS_THREADS
78#error The Event MPM requires APR threads, but they are unavailable.
79#endif
80
81#include "ap_config.h"
82#include "httpd.h"
83#include "http_main.h"
84#include "http_log.h"
85#include "http_config.h" /* for read_config */
86#include "http_core.h" /* for get_remote_host */
87#include "http_connection.h"
88#include "http_protocol.h"
89#include "ap_mpm.h"
90#include "mpm_common.h"
91#include "ap_listen.h"
92#include "scoreboard.h"
93#include "mpm_fdqueue.h"
94#include "mpm_default.h"
95#include "http_vhost.h"
96#include "unixd.h"
97#include "apr_skiplist.h"
98
99#include <signal.h>
100#include <limits.h> /* for INT_MAX */
101
102
103/* Limit on the total --- clients will be locked out if more servers than
104 * this are needed. It is intended solely to keep the server from crashing
105 * when things get out of hand.
106 *
107 * We keep a hard maximum number of servers, for two reasons --- first off,
108 * in case something goes seriously wrong, we want to stop the fork bomb
109 * short of actually crashing the machine we're running on by filling some
110 * kernel table. Secondly, it keeps the size of the scoreboard file small
111 * enough that we can read the whole thing without worrying too much about
112 * the overhead.
113 */
114#ifndef DEFAULT_SERVER_LIMIT
115#define DEFAULT_SERVER_LIMIT 16
116#endif
117
118/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
119 * some sort of compile-time limit to help catch typos.
120 */
121#ifndef MAX_SERVER_LIMIT
122#define MAX_SERVER_LIMIT 20000
123#endif
124
125/* Limit on the threads per process. Clients will be locked out if more than
126 * this are needed.
127 *
128 * We keep this for one reason it keeps the size of the scoreboard file small
129 * enough that we can read the whole thing without worrying too much about
130 * the overhead.
131 */
132#ifndef DEFAULT_THREAD_LIMIT
133#define DEFAULT_THREAD_LIMIT 64
134#endif
135
136/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
137 * some sort of compile-time limit to help catch typos.
138 */
139#ifndef MAX_THREAD_LIMIT
140#define MAX_THREAD_LIMIT 100000
141#endif
142
143#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
144
145#if !APR_VERSION_AT_LEAST(1,4,0)
146#define apr_time_from_msec(x) (x * 1000)
147#endif
148
149#ifndef MAX_SECS_TO_LINGER
150#define MAX_SECS_TO_LINGER 30
151#endif
152#define SECONDS_TO_LINGER 2
153
154/*
155 * Actual definitions of config globals
156 */
157
158#ifndef DEFAULT_WORKER_FACTOR
159#define DEFAULT_WORKER_FACTOR 2
160#endif
161#define WORKER_FACTOR_SCALE 16 /* scale factor to allow fractional values */
163 /* AsyncRequestWorkerFactor * 16 */
164
165static int threads_per_child = 0; /* ThreadsPerChild */
166static int ap_daemons_to_start = 0; /* StartServers */
167static int min_spare_threads = 0; /* MinSpareThreads */
168static int max_spare_threads = 0; /* MaxSpareThreads */
169static int active_daemons_limit = 0; /* MaxRequestWorkers / ThreadsPerChild */
170static int max_workers = 0; /* MaxRequestWorkers */
171static int server_limit = 0; /* ServerLimit */
172static int thread_limit = 0; /* ThreadLimit */
173static int had_healthy_child = 0;
174static volatile int dying = 0;
175static volatile int workers_may_exit = 0;
176static volatile int start_thread_may_exit = 0;
177static volatile int listener_may_exit = 0;
178static int listener_is_wakeable = 0; /* Pollset supports APR_POLLSET_WAKEABLE */
179static int num_listensocks = 0;
180static apr_int32_t conns_this_child; /* MaxConnectionsPerChild, only access
181 in listener thread */
182static apr_uint32_t connection_count = 0; /* Number of open connections */
183static apr_uint32_t lingering_count = 0; /* Number of connections in lingering close */
184static apr_uint32_t suspended_count = 0; /* Number of suspended connections */
185static apr_uint32_t clogged_count = 0; /* Number of threads processing ssl conns */
186static apr_uint32_t threads_shutdown = 0; /* Number of threads that have shutdown
187 early during graceful termination */
188static int resource_shortage = 0;
191
193
194module AP_MODULE_DECLARE_DATA mpm_event_module;
195
196/* forward declare */
197struct event_srv_cfg_s;
199
201
202/*
203 * The pollset for sockets that are in any of the timeout queues. Currently
204 * we use the timeout_mutex to make sure that connections are added/removed
205 * atomically to/from both event_pollset and a timeout queue. Otherwise
206 * some confusion can happen under high load if timeout queues and pollset
207 * get out of sync.
208 * XXX: It should be possible to make the lock unnecessary in many or even all
209 * XXX: cases.
210 */
212
214
215/*
216 * The chain of connections to be shutdown by a worker thread (deferred),
217 * linked list updated atomically.
218 */
220
252
254
258 apr_uint32_t count; /* for this queue */
259 apr_uint32_t *total; /* for all chained/related queues */
260 struct timeout_queue *next; /* chaining */
261};
262/*
263 * Several timeout queues that use different timeouts, so that we always can
264 * simply append to the end.
265 * write_completion_q uses vhost's TimeOut
266 * keepalive_q uses vhost's KeepAliveTimeOut
267 * linger_q uses MAX_SECS_TO_LINGER
268 * short_linger_q uses SECONDS_TO_LINGER
269 */
275
276/* Prevent extra poll/wakeup calls for timeouts close in the future (queues
277 * have the granularity of a second anyway).
278 * XXX: Wouldn't 0.5s (instead of 0.1s) be "enough"?
279 */
280#define TIMEOUT_FUDGE_FACTOR apr_time_from_msec(100)
281
282/*
283 * Macros for accessing struct timeout_queue.
284 * For TO_QUEUE_APPEND and TO_QUEUE_REMOVE, timeout_mutex must be held.
285 */
287{
290
291 APR_RING_INSERT_TAIL(&q->head, el, event_conn_state_t, timeout_list);
292 ++*q->total;
293 ++q->count;
294
295 /* Cheaply update the global queues_next_expiry with the one of the
296 * first entry of this queue (oldest) if it expires before.
297 */
298 el = APR_RING_FIRST(&q->head);
299 elem_expiry = el->queue_timestamp + q->timeout;
303 /* Unblock the poll()ing listener for it to update its timeout. */
306 }
307 }
308}
309
311{
312 APR_RING_REMOVE(el, timeout_list);
313 APR_RING_ELEM_INIT(el, timeout_list);
314 --*q->total;
315 --q->count;
316}
317
319 struct timeout_queue *ref)
320{
321 struct timeout_queue *q;
322
323 q = apr_pcalloc(p, sizeof *q);
324 APR_RING_INIT(&q->head, event_conn_state_t, timeout_list);
325 q->total = (ref) ? ref->total : apr_pcalloc(p, sizeof *q->total);
326 q->timeout = t;
327
328 return q;
329}
330
331#define TO_QUEUE_ELEM_INIT(el) \
332 APR_RING_ELEM_INIT((el), timeout_list)
333
334/* The structure used to pass unique initialization info to each thread */
335typedef struct
336{
337 int pslot; /* process slot */
338 int tslot; /* worker slot of the thread */
339} proc_info;
340
341/* Structure used to pass information to the thread responsible for
342 * creating the rest of the threads.
343 */
351
352typedef enum
353{
357
358typedef struct
359{
361 void *baton;
363
364/* data retained by event across load/unload of the module
365 * allocated on first call to pre-config hook; located on
366 * subsequent calls to pre-config hook
367 */
368typedef struct event_retained_data {
370
376 /*
377 * The max child slot ever assigned, preserved across restarts. Necessary
378 * to deal with MaxRequestWorkers changes across AP_SIG_GRACEFUL restarts.
379 * We use this value to optimize routines that have to scan the entire
380 * scoreboard.
381 */
383
384 /*
385 * All running workers, active and shutting down, including those that
386 * may be left from before a graceful restart.
387 * Not kept up-to-date when shutdown is pending.
388 */
390 /*
391 * Workers that still active, i.e. are not shutting down gracefully.
392 */
394 /*
395 * idle_spawn_rate is the number of children that will be spawned on the
396 * next maintenance cycle if there aren't enough idle servers. It is
397 * maintained per listeners bucket, doubled up to MAX_SPAWN_RATE, and
398 * reset only when a cycle goes by without the need to spawn.
399 */
401#ifndef MAX_SPAWN_RATE
402#define MAX_SPAWN_RATE (32)
403#endif
407
412static event_child_bucket *all_buckets, /* All listeners buckets */
413 *my_bucket; /* Current child bucket */
414
419
420#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
421
422/* The event MPM respects a couple of runtime flags that can aid
423 * in debugging. Setting the -DNO_DETACH flag will prevent the root process
424 * from detaching from its controlling terminal. Additionally, setting
425 * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
426 * child_main loop running in the process which originally started up.
427 * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
428 * early in standalone_main; just continue through. This is the server
429 * trying to kill off any child processes which it might have lying
430 * around --- Apache doesn't keep track of their pids, it just sends
431 * SIGHUP to the process group, ignoring it in the root process.
432 * Continue through and you'll be fine.).
433 */
434
435static int one_process = 0;
436
437#ifdef DEBUG_SIGSTOP
439#endif
440
441static apr_pool_t *pconf; /* Pool for config stuff */
442static apr_pool_t *pchild; /* Pool for httpd child stuff */
443static apr_pool_t *pruntime; /* Pool for MPM threads stuff */
444
445static pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
446 thread. Use this instead */
449
450static int ap_child_slot; /* Current child process slot in scoreboard */
451
452/* The LISTENER_SIGNAL signal will be sent from the main thread to the
453 * listener thread to wake it up for graceful termination (what a child
454 * process from an old generation does when the admin does "apachectl
455 * graceful"). This signal will be blocked in all threads of a child
456 * process except for the listener thread.
457 */
458#define LISTENER_SIGNAL SIGHUP
459
460/* An array of socket descriptors in use by each thread used to
461 * perform a non-graceful (forced) shutdown of the server.
462 */
464
466
467static void disable_listensocks(void)
468{
469 int i;
470 if (apr_atomic_cas32(&listensocks_disabled, 1, 0) != 0) {
471 return;
472 }
473 if (event_pollset) {
474 for (i = 0; i < num_listensocks; i++) {
476 }
477 }
479}
480
481static void enable_listensocks(void)
482{
483 int i;
485 || apr_atomic_cas32(&listensocks_disabled, 0, 1) != 1) {
486 return;
487 }
489 "Accepting new connections again: "
490 "%u active conns (%u lingering/%u clogged/%u suspended), "
491 "%u idle workers",
497 for (i = 0; i < num_listensocks; i++)
499 /*
500 * XXX: This is not yet optimal. If many workers suddenly become available,
501 * XXX: the parent may kill some processes off too soon.
502 */
504}
505
510
512{
514 if (i_count > 0) {
517 if (c_count <= l_count
518 /* Off by 'listeners_disabled()' to avoid flip flop */
522 return 0;
523 }
524 }
525 else if (busy) {
526 *busy = 1;
527 }
528 return 1;
529}
530
535
537 const char *from, int line)
538{
539 apr_status_t rv;
540 apr_os_sock_t fd = -1;
541
542 /* close_worker_sockets() may have closed it already */
543 rv = apr_os_sock_get(&fd, csd);
545 "closing socket %i/%pp from %s:%i", (int)fd, csd, from, line);
546 if (rv == APR_SUCCESS && fd == -1) {
547 return;
548 }
549
551 rv = apr_socket_close(csd);
552 if (rv != APR_SUCCESS) {
554 "error closing socket");
556 }
557}
558#define close_socket_nonblocking(csd) \
559 close_socket_nonblocking_(csd, __FUNCTION__, __LINE__)
560
561static void close_worker_sockets(void)
562{
563 int i;
564 for (i = 0; i < threads_per_child; i++) {
566 if (csd) {
569 }
570 }
571}
572
573static void wakeup_listener(void)
574{
576 "wake up listener%s", listener_may_exit ? " again" : "");
577
580
581 /* Unblock the listener if it's poll()ing */
584 }
585
586 /* unblock the listener if it's waiting for a worker */
587 if (worker_queue_info) {
589 }
590
591 if (!listener_os_thread) {
592 /* XXX there is an obscure path that this doesn't handle perfectly:
593 * right after listener thread is created but before
594 * listener_os_thread is set, the first worker thread hits an
595 * error and starts graceful termination
596 */
597 return;
598 }
599 /*
600 * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
601 * platforms and wake up the listener thread since it is the only thread
602 * with SIGHUP unblocked, but that doesn't work on Linux
603 */
604#ifdef HAVE_PTHREAD_KILL
606#else
608#endif
609}
610
611#define ST_INIT 0
612#define ST_GRACEFUL 1
613#define ST_UNGRACEFUL 2
614
616
617static void signal_threads(int mode)
618{
619 if (terminate_mode >= mode) {
620 return;
621 }
623 retained->mpm->mpm_state = AP_MPMQ_STOPPING;
624
625 /* in case we weren't called from the listener thread, wake up the
626 * listener thread
627 */
629
630 /* for ungraceful termination, let the workers exit now;
631 * for graceful termination, the listener thread will notify the
632 * workers to exit once it has stopped accepting new connections
633 */
634 if (mode == ST_UNGRACEFUL) {
637 close_worker_sockets(); /* forcefully kill all current connections */
638 }
639
641}
642
643static int event_query(int query_code, int *result, apr_status_t *rv)
644{
645 *rv = APR_SUCCESS;
646 switch (query_code) {
649 break;
652 break;
655 break;
656 case AP_MPMQ_IS_ASYNC:
657 *result = 1;
658 break;
661 break;
664 break;
667 break;
669 *result = 0;
670 break;
673 break;
675 *result = 0;
676 break;
679 break;
682 break;
685 break;
687 *result = retained->mpm->mpm_state;
688 break;
690 *result = retained->mpm->my_generation;
691 break;
692 default:
693 *rv = APR_ENOTIMPL;
694 break;
695 }
696 return OK;
697}
698
700{
701 if (slot != -1) { /* child had a scoreboard slot? */
703 int i;
704
705 pid = ps->pid;
706 gen = ps->generation;
707 for (i = 0; i < threads_per_child; i++) {
709 }
711 if (ps->quiescing != 2) { /* vs perform_idle_server_maintenance() */
713 }
716 "Child %d stopped: pid %d, gen %d, "
717 "active %d/%d, total %d/%d/%d, quiescing %d",
718 slot, (int)pid, (int)gen,
721 server_limit, ps->quiescing);
722 ps->not_accepting = 0;
723 ps->quiescing = 0;
724 ps->pid = 0;
725 }
726 else {
728 }
729}
730
732{
733 ap_generation_t gen = retained->mpm->my_generation;
734
741 "Child %d started: pid %d, gen %d, "
742 "active %d/%d, total %d/%d/%d",
743 slot, (int)pid, (int)gen,
747}
748
749static const char *event_get_name(void)
750{
751 return "event";
752}
753
754/* a clean exit from a child with proper cleanup */
755static void clean_child_exit(int code) __attribute__ ((noreturn));
756static void clean_child_exit(int code)
757{
758 retained->mpm->mpm_state = AP_MPMQ_STOPPING;
759 if (terminate_mode == ST_INIT) {
761 }
762
763 if (pchild) {
765 }
766
767 if (one_process) {
768 event_note_child_stopped(/* slot */ 0, 0, 0);
769 }
770
771 exit(code);
772}
773
774static void just_die(int sig)
775{
777}
778
779/*****************************************************************
780 * Connection structures and accounting...
781 */
782
783static int child_fatal;
784
786{
790 "cleanup connection from state %i", (int)cs->pub.state);
791 switch (cs->pub.state) {
796 break;
799 break;
800 default:
801 break;
802 }
803 /* Unblock the listener if it's waiting for connection_count = 0,
804 * or if the listening sockets were disabled due to limits and can
805 * now accept new connections.
806 */
812 }
813 if (dying) {
814 /* Help worker_thread_should_exit_early() */
816 }
817 return APR_SUCCESS;
818}
819
821{
822 ap_run_suspend_connection(cs->c, cs->r);
823 cs->c->sbh = NULL;
824 cs->suspended = 1;
825}
826
828{
829 cs->suspended = 0;
830 cs->c->sbh = cleanup ? NULL : cs->sbh;
831 ap_run_resume_connection(cs->c, cs->r);
832}
833
834/*
835 * Defer flush and close of the connection by adding it to defer_linger_chain,
836 * for a worker to grab it and do the job (should that be blocking).
837 * Pre-condition: nonblocking, can be called from anywhere provided cs is not
838 * in any timeout queue or in the pollset.
839 */
841{
843 "deferring close from state %i", (int)cs->pub.state);
844
845 /* The connection is not shutdown() yet strictly speaking, but it's not
846 * in any queue nor handled by a worker either (will be very soon), so
847 * to account for it somewhere we bump lingering_count now (and set
848 * deferred_linger for process_lingering_close() to know).
849 */
852 cs->deferred_linger = 1;
853 for (;;) {
855 if (apr_atomic_casptr((void *)&defer_linger_chain, cs,
856 chain) != chain) {
857 /* Race lost, try again */
858 continue;
859 }
860 return 1;
861 }
862}
863
864/* Close the connection and release its resources (ptrans), either because an
865 * unrecoverable error occured (queues or pollset add/remove) or more usually
866 * if lingering close timed out.
867 * Pre-condition: nonblocking, can be called from anywhere provided cs is not
868 * in any timeout queue or in the pollset.
869 */
871{
873 "closing connection from state %i", (int)cs->pub.state);
874
877}
878
879/* Shutdown the connection in case of timeout, error or resources shortage.
880 * This starts short lingering close if not already there, or directly closes
881 * the connection otherwise.
882 * Pre-condition: nonblocking, can be called from anywhere provided cs is not
883 * in any timeout queue or in the pollset.
884 */
886{
887 if (cs->pub.state < CONN_STATE_LINGER) {
888 apr_table_setn(cs->c->notes, "short-lingering-close", "1");
890 }
891 else {
893 }
894 return 1;
895}
896
897/*
898 * This runs before any non-MPM cleanup code on the connection;
899 * if the connection is currently suspended as far as modules
900 * know, provide notification of resumption.
901 */
903{
905
906 if (cs->suspended) {
907 notify_resume(cs, 1);
908 }
909 return APR_SUCCESS;
910}
911
912/*
913 * event_pre_read_request() and event_request_cleanup() track the
914 * current r for a given connection.
915 */
917{
918 conn_rec *c = dummy;
919 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
920 &mpm_event_module);
921
922 cs->r = NULL;
923 return APR_SUCCESS;
924}
925
927{
928 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
929 &mpm_event_module);
930
931 cs->r = r;
933 &mpm_event_module);
936}
937
938/*
939 * event_post_read_request() tracks the current server config for a
940 * given request.
941 */
943{
945 event_conn_state_t *cs = ap_get_module_config(c->conn_config,
946 &mpm_event_module);
947
948 /* To preserve legacy behaviour (consistent with other MPMs), use
949 * the keepalive timeout from the base server (first on this IP:port)
950 * when none is explicitly configured on this server.
951 */
954 &mpm_event_module);
955 }
956 else {
957 cs->sc = ap_get_module_config(c->base_server->module_config,
958 &mpm_event_module);
959 }
960 return OK;
961}
962
963/* Forward declare */
965
967{
968 if (sense < 0) {
969 sense = cs->pub.sense;
970 }
971 if (sense == CONN_SENSE_WANT_READ) {
973 }
974 else {
976 }
977 /* POLLERR is usually returned event only, but some pollset
978 * backends may require it in reqevents to do the right thing,
979 * so it shouldn't hurt (ignored otherwise).
980 */
982
983 /* Reset to default for the next round */
985}
986
987/*
988 * process one connection in the worker
989 */
992 int my_thread_num)
993{
994 conn_rec *c;
996 int clogging = 0;
997 apr_status_t rv;
998 int rc = OK;
999
1000 if (cs == NULL) { /* This is a new connection */
1001 listener_poll_type *pt = apr_pcalloc(p, sizeof(*pt));
1002 cs = apr_pcalloc(p, sizeof(event_conn_state_t));
1006 conn_id, cs->sbh, cs->bucket_alloc);
1007 if (!c) {
1009 return;
1010 }
1014 ap_set_module_config(c->conn_config, &mpm_event_module, cs);
1015 c->current_thread = thd;
1016 c->cs = &cs->pub;
1017 cs->c = c;
1018 cs->p = p;
1020 &mpm_event_module);
1022 cs->pfd.desc.s = sock;
1024 pt->type = PT_CSD;
1025 pt->baton = cs;
1026 cs->pfd.client_data = pt;
1029
1031
1033 if (rc != OK && rc != DONE) {
1035 "process_socket: connection aborted");
1036 }
1037
1052
1054 rc = OK;
1055 }
1056 else {
1057 c = cs->c;
1059 notify_resume(cs, 0);
1060 c->current_thread = thd;
1061 /* Subsequent request on a conn, and thread number is part of ID */
1062 c->id = conn_id;
1063 }
1064
1065 if (c->aborted) {
1066 /* do lingering close below */
1068 }
1069 else if (cs->pub.state >= CONN_STATE_LINGER) {
1070 /* fall through */
1071 }
1072 else {
1074 /* If we have an input filter which 'clogs' the input stream,
1075 * like mod_ssl used to, lets just do the normal read from input
1076 * filters, like the Worker MPM does. Filters that need to write
1077 * where they would otherwise read, or read where they would
1078 * otherwise write, should set the sense appropriately.
1079 */
1080 || c->clogging_input_filters) {
1082 clogging = c->clogging_input_filters;
1083 if (clogging) {
1085 }
1087 if (clogging) {
1089 }
1090 if (cs->pub.state > CONN_STATE_LINGER) {
1092 }
1093 if (rc == DONE) {
1094 rc = OK;
1095 }
1096 }
1097 }
1098 /*
1099 * The process_connection hooks above should set the connection state
1100 * appropriately upon return, for event MPM to either:
1101 * - do lingering close (CONN_STATE_LINGER),
1102 * - wait for readability of the next request with respect to the keepalive
1103 * timeout (state CONN_STATE_CHECK_REQUEST_LINE_READABLE),
1104 * - wait for read/write-ability of the underlying socket with respect to
1105 * its timeout by setting c->clogging_input_filters to 1 and the sense
1106 * to CONN_SENSE_WANT_READ/WRITE (state CONN_STATE_WRITE_COMPLETION),
1107 * - keep flushing the output filters stack in nonblocking mode, and then
1108 * if required wait for read/write-ability of the underlying socket with
1109 * respect to its own timeout (state CONN_STATE_WRITE_COMPLETION); since
1110 * completion at some point may require reads (e.g. SSL_ERROR_WANT_READ),
1111 * an output filter can also set the sense to CONN_SENSE_WANT_READ at any
1112 * time for event MPM to do the right thing,
1113 * - suspend the connection (SUSPENDED) such that it now interacts with
1114 * the MPM through suspend/resume_connection() hooks, and/or registered
1115 * poll callbacks (PT_USER), and/or registered timed callbacks triggered
1116 * by timer events.
1117 * If a process_connection hook returns an error or no hook sets the state
1118 * to one of the above expected value, we forcibly close the connection w/
1119 * CONN_STATE_LINGER. This covers the cases where no process_connection
1120 * hook executes (DECLINED), or one returns OK w/o touching the state (i.e.
1121 * CONN_STATE_READ_REQUEST_LINE remains after the call) which can happen
1122 * with third-party modules not updated to work specifically with event MPM
1123 * while this was expected to do lingering close unconditionally with
1124 * worker or prefork MPMs for instance.
1125 */
1126 if (rc != OK || (cs->pub.state >= CONN_STATE_NUM)
1127 || (cs->pub.state < CONN_STATE_LINGER
1130 && cs->pub.state != CONN_STATE_SUSPENDED)) {
1132 "process_socket: connection processing %s: closing",
1133 rc ? apr_psprintf(c->pool, "returned error %i", rc)
1134 : apr_psprintf(c->pool, "unexpected state %i",
1135 (int)cs->pub.state));
1137 }
1138
1140 ap_filter_t *output_filter = c->output_filters;
1141 apr_status_t rv;
1143 while (output_filter->next != NULL) {
1145 }
1146 rv = output_filter->frec->filter_func.out_func(output_filter, NULL);
1147 if (rv != APR_SUCCESS) {
1149 "network write failure in core output filter");
1151 }
1152 else if (c->data_in_output_filters ||
1154 /* Still in WRITE_COMPLETION_STATE:
1155 * Set a read/write timeout for this connection, and let the
1156 * event thread poll for read/writeability.
1157 */
1159 notify_suspend(cs);
1160
1163 TO_QUEUE_APPEND(cs->sc->wc_q, cs);
1164 rv = apr_pollset_add(event_pollset, &cs->pfd);
1165 if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
1166 AP_DEBUG_ASSERT(0);
1167 TO_QUEUE_REMOVE(cs->sc->wc_q, cs);
1170 "process_socket: apr_pollset_add failure for "
1171 "write completion");
1172 close_connection(cs);
1174 }
1175 else {
1177 }
1178 return;
1179 }
1180 else if (c->keepalive != AP_CONN_KEEPALIVE || c->aborted) {
1182 }
1183 else if (c->data_in_input_filters) {
1185 goto read_request;
1186 }
1187 else if (!listener_may_exit) {
1189 }
1190 else {
1192 }
1193 }
1194
1197
1198 /* It greatly simplifies the logic to use a single timeout value per q
1199 * because the new element can just be added to the end of the list and
1200 * it will stay sorted in expiration time sequence. If brand new
1201 * sockets are sent to the event thread for a readability check, this
1202 * will be a slight behavior change - they use the non-keepalive
1203 * timeout today. With a normal client, the socket will be readable in
1204 * a few milliseconds anyway.
1205 */
1207 notify_suspend(cs);
1208
1209 /* Add work to pollset. */
1212 TO_QUEUE_APPEND(cs->sc->ka_q, cs);
1213 rv = apr_pollset_add(event_pollset, &cs->pfd);
1214 if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
1215 AP_DEBUG_ASSERT(0);
1216 TO_QUEUE_REMOVE(cs->sc->ka_q, cs);
1219 "process_socket: apr_pollset_add failure for "
1220 "keep alive");
1221 close_connection(cs);
1223 }
1224 else {
1226 }
1227 return;
1228 }
1229
1230 if (cs->pub.state == CONN_STATE_SUSPENDED) {
1232 notify_suspend(cs);
1233 return;
1234 }
1235
1236 /* CONN_STATE_LINGER[_*] fall through process_lingering_close() */
1237 if (cs->pub.state >= CONN_STATE_LINGER) {
1239 return;
1240 }
1241}
1242
1243/* conns_this_child has gone to zero or below. See if the admin coded
1244 "MaxConnectionsPerChild 0", and keep going in that case. Doing it this way
1245 simplifies the hot path in worker_thread */
1247{
1250 "Stopping process due to MaxConnectionsPerChild");
1252 }
1253 else {
1254 /* keep going */
1256 }
1257}
1258
1259static int close_listeners(int *closed)
1260{
1262 "clos%s listeners (connection_count=%u)",
1263 *closed ? "ed" : "ing", apr_atomic_read32(&connection_count));
1264 if (!*closed) {
1265 int i;
1266
1268 *closed = 1; /* once */
1269
1270 dying = 1;
1272 for (i = 0; i < threads_per_child; ++i) {
1275 }
1276 /* wake up the main thread */
1278
1281
1282 return 1;
1283 }
1284 return 0;
1285}
1286
1287static void unblock_signal(int sig)
1288{
1290
1293#if defined(SIGPROCMASK_SETS_THREAD_MASK)
1295#else
1297#endif
1298}
1299
1301{
1302 /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
1303 * then we don't need this goofy function.
1304 */
1305}
1306
1307
1312
1313/*
1314 * Pre-condition: cs is neither in event_pollset nor a timeout queue
1315 * this function may only be called by the listener
1316 */
1319{
1321
1322 if (cs) {
1323 csd = cs->pfd.desc.s;
1324 ptrans = cs->p;
1325 }
1327 if (rc != APR_SUCCESS) {
1329 "push2worker: ap_queue_push_socket failed");
1330 /* trash the connection; we couldn't queue the connected
1331 * socket to a worker
1332 */
1333 if (cs) {
1335 }
1336 else {
1337 if (csd) {
1339 }
1340 if (ptrans) {
1342 }
1343 }
1345 }
1346
1347 return rc;
1348}
1349
1350/* get_worker:
1351 * If *have_idle_worker_p == 0, reserve a worker thread, and set
1352 * *have_idle_worker_p = 1.
1353 * If *have_idle_worker_p is already 1, will do nothing.
1354 * If blocking == 1, block if all workers are currently busy.
1355 * If no worker was available immediately, will set *all_busy to 1.
1356 * XXX: If there are no workers, we should not block immediately but
1357 * XXX: close all keep-alive connections first.
1358 */
1360{
1362
1363 if (*have_idle_worker_p) {
1364 /* already reserved a worker thread - must have hit a
1365 * transient error on a previous pass
1366 */
1367 return;
1368 }
1369
1370 if (blocking)
1372 else
1374
1375 if (rc == APR_SUCCESS || APR_STATUS_IS_EOF(rc)) {
1376 *have_idle_worker_p = 1;
1377 }
1378 else if (!blocking && rc == APR_EAGAIN) {
1379 *all_busy = 1;
1380 }
1381 else {
1383 "ap_queue_info_wait_for_idler failed. "
1384 "Attempting to shutdown process gracefully");
1386 }
1387}
1388
1389/* Structures to reuse */
1391
1394
1395/* Same goal as for TIMEOUT_FUDGE_FACTOR (avoid extra poll calls), but applied
1396 * to timers. Since their timeouts are custom (user defined), we can't be too
1397 * approximative here (hence using 0.01s).
1398 */
1399#define EVENT_FUDGE_FACTOR apr_time_from_msec(10)
1400
1401/* The following compare function is used by apr_skiplist_insert() to keep the
1402 * elements (timers) sorted and provide O(log n) complexity (this is also true
1403 * for apr_skiplist_{find,remove}(), but those are not used in MPM event where
1404 * inserted timers are not searched nor removed, but with apr_skiplist_pop()
1405 * which does use any compare function). It is meant to return 0 when a == b,
1406 * <0 when a < b, and >0 when a > b. However apr_skiplist_insert() will not
1407 * add duplicates (i.e. a == b), and apr_skiplist_add() is only available in
1408 * APR 1.6, yet multiple timers could possibly be created in the same micro-
1409 * second (duplicates with regard to apr_time_t); therefore we implement the
1410 * compare function to return +1 instead of 0 when compared timers are equal,
1411 * thus duplicates are still added after each other (in order of insertion).
1412 */
1413static int timer_comp(void *a, void *b)
1414{
1419 return ((t1 < t2) ? -1 : 1);
1420}
1421
1423
1426 void *baton)
1427{
1429 /* oh yeah, and make locking smarter/fine grained. */
1431
1432 if (!APR_RING_EMPTY(&timer_free_ring.link, timer_event_t, link)) {
1434 APR_RING_REMOVE(te, link);
1435 }
1436 else {
1438 APR_RING_ELEM_INIT(te, link);
1439 }
1440
1441 te->cbfunc = cbfn;
1442 te->baton = baton;
1443 /* XXXXX: optimize */
1444 te->when = t + apr_time_now();
1445
1446 {
1448
1449 /* Okay, add sorted by when.. */
1451
1452 /* Cheaply update the global timers_next_expiry with this event's
1453 * if it expires before.
1454 */
1456 if (!next_expiry || next_expiry > te->when + EVENT_FUDGE_FACTOR) {
1457 timers_next_expiry = te->when;
1458 /* Unblock the poll()ing listener for it to update its timeout. */
1461 }
1462 }
1463 }
1464
1466
1467 return APR_SUCCESS;
1468}
1469
1470
1471/*
1472 * Flush data and close our side of the connection, then drain incoming data.
1473 * If the latter would block put the connection in one of the linger timeout
1474 * queues to be called back when ready, and repeat until it's closed by peer.
1475 * Only to be called in the worker thread, and since it's in immediate call
1476 * stack, we can afford a comfortable buffer size to consume data quickly.
1477 * Pre-condition: cs is not in any timeout queue and not in the pollset,
1478 * timeout_mutex is not locked
1479 */
1480#define LINGERING_BUF_SIZE (32 * 1024)
1482{
1486 apr_status_t rv;
1487 struct timeout_queue *q;
1488
1490 "lingering close from state %i", (int)cs->pub.state);
1492
1493 if (cs->pub.state == CONN_STATE_LINGER) {
1494 /* defer_lingering_close() may have bumped lingering_count already */
1495 if (!cs->deferred_linger) {
1497 }
1498
1500 if (ap_start_lingering_close(cs->c)) {
1501 notify_suspend(cs);
1502 close_connection(cs);
1503 return;
1504 }
1505
1507 /* Clear APR_INCOMPLETE_READ if it was ever set, we'll do the poll()
1508 * at the listener only from now, if needed.
1509 */
1511 /*
1512 * If some module requested a shortened waiting period, only wait for
1513 * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
1514 * DoS attacks.
1515 */
1516 if (apr_table_get(cs->c->notes, "short-lingering-close")) {
1518 }
1519 else {
1521 }
1522 notify_suspend(cs);
1523 }
1524
1526 do {
1527 nbytes = sizeof(dummybuf);
1529 } while (rv == APR_SUCCESS);
1530
1531 if (!APR_STATUS_IS_EAGAIN(rv)) {
1532 close_connection(cs);
1533 return;
1534 }
1535
1536 /* (Re)queue the connection to come back when readable */
1540 TO_QUEUE_APPEND(q, cs);
1541 rv = apr_pollset_add(event_pollset, &cs->pfd);
1542 if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
1543 AP_DEBUG_ASSERT(0);
1544 TO_QUEUE_REMOVE(q, cs);
1547 "process_lingering_close: apr_pollset_add failure");
1548 close_connection(cs);
1550 return;
1551 }
1553}
1554
1555/* call 'func' for all elements of 'q' above 'expiry'.
1556 * Pre-condition: timeout_mutex must already be locked
1557 * Post-condition: timeout_mutex will be locked again
1558 */
1559static void process_timeout_queue(struct timeout_queue *q, apr_time_t expiry,
1560 int (*func)(event_conn_state_t *))
1561{
1565 struct timeout_queue *qp;
1566 apr_status_t rv;
1567
1568 if (!*q->total) {
1569 return;
1570 }
1571
1572 APR_RING_INIT(&trash.timeout_list, event_conn_state_t, timeout_list);
1573 for (qp = q; qp; qp = qp->next) {
1574 count = 0;
1575 cs = first = last = APR_RING_FIRST(&qp->head);
1576 while (cs != APR_RING_SENTINEL(&qp->head, event_conn_state_t,
1577 timeout_list)) {
1578 /* Trash the entry if:
1579 * - no expiry was given (zero means all), or
1580 * - it expired (according to the queue timeout), or
1581 * - the system clock skewed in the past: no entry should be
1582 * registered above the given expiry (~now) + the queue
1583 * timeout, we won't keep any here (eg. for centuries).
1584 *
1585 * Otherwise stop, no following entry will match thanks to the
1586 * single timeout per queue (entries are added to the end!).
1587 * This allows maintenance in O(1).
1588 */
1589 if (expiry && cs->queue_timestamp + qp->timeout > expiry
1590 && cs->queue_timestamp < expiry + qp->timeout) {
1591 /* Since this is the next expiring entry of this queue, update
1592 * the global queues_next_expiry if it's later than this one.
1593 */
1594 apr_time_t elem_expiry = cs->queue_timestamp + qp->timeout;
1596 if (!next_expiry
1599 }
1600 break;
1601 }
1602
1603 last = cs;
1605 if (rv != APR_SUCCESS && !APR_STATUS_IS_NOTFOUND(rv)) {
1606 AP_DEBUG_ASSERT(0);
1607 ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, cs->c, APLOGNO(00473)
1608 "apr_pollset_remove failed");
1609 }
1610 cs = APR_RING_NEXT(cs, timeout_list);
1611 count++;
1612 }
1613 if (!count)
1614 continue;
1615
1616 APR_RING_UNSPLICE(first, last, timeout_list);
1618 timeout_list);
1619 AP_DEBUG_ASSERT(*q->total >= count && qp->count >= count);
1620 *q->total -= count;
1621 qp->count -= count;
1622 total += count;
1623 }
1624 if (!total)
1625 return;
1626
1628 first = APR_RING_FIRST(&trash.timeout_list);
1629 do {
1630 cs = APR_RING_NEXT(first, timeout_list);
1632 func(first);
1633 first = cs;
1634 } while (--total);
1636}
1637
1639{
1640 /* If all workers are busy, we kill older keep-alive connections so
1641 * that they may connect to another process.
1642 */
1643 if (!expiry && *keepalive_q->total) {
1645 "All workers are busy or dying, will shutdown %u "
1646 "keep-alive connections", *keepalive_q->total);
1647 }
1649}
1650
1652{
1654 proc_info *ti = dummy;
1655 int process_slot = ti->pslot;
1657 int closed = 0;
1658 int have_idle_worker = 0;
1660
1662 free(ti);
1663
1664 /* Unblock the signal used to wake this thread up, and set a handler for
1665 * it.
1666 */
1669
1670 for (;;) {
1672 const apr_pollfd_t *out_pfd;
1673 apr_int32_t num = 0;
1675 apr_time_t now, expiry = -1;
1676 int workers_were_busy = 0;
1677
1678 if (conns_this_child <= 0)
1680
1681 if (listener_may_exit) {
1682 int first_close = close_listeners(&closed);
1683
1686 break;
1687
1688 /* Don't wait in poll() for the first close (i.e. dying now), we
1689 * want to maintain the queues and schedule defer_linger_chain ASAP
1690 * to kill kept-alive connection and shutdown the workers and child
1691 * faster.
1692 */
1693 if (first_close) {
1694 goto do_maintenance; /* with expiry == -1 */
1695 }
1696 }
1697
1698 now = apr_time_now();
1700 /* trace log status every second */
1701 if (now - last_log > apr_time_from_sec(1)) {
1702 last_log = now;
1705 "connections: %u (clogged: %u write-completion: %d "
1706 "keep-alive: %d lingering: %d suspended: %u)",
1713 if (dying) {
1715 "%u/%u workers shutdown",
1718 }
1720 }
1721 }
1722
1723 /* Start with an infinite poll() timeout and update it according to
1724 * the next expiring timer or queue entry. If there are none, either
1725 * the listener is wakeable and it can poll() indefinitely until a wake
1726 * up occurs, otherwise periodic checks (maintenance, shutdown, ...)
1727 * must be performed.
1728 */
1729 now = apr_time_now();
1730 timeout = -1;
1731
1732 /* Push expired timers to a worker, the first remaining one determines
1733 * the maximum time to poll() below, if any.
1734 */
1735 expiry = timers_next_expiry;
1736 if (expiry && expiry < now) {
1738 while ((te = apr_skiplist_peek(timer_skiplist))) {
1739 if (te->when > now) {
1740 timers_next_expiry = te->when;
1741 timeout = te->when - now;
1742 break;
1743 }
1746 }
1747 if (!te) {
1749 }
1751 }
1752
1753 /* Same for queues, use their next expiry, if any. */
1754 expiry = queues_next_expiry;
1755 if (expiry
1756 && (timeout < 0
1757 || expiry <= now
1758 || timeout > expiry - now)) {
1759 timeout = expiry > now ? expiry - now : 0;
1760 }
1761
1762 /* When non-wakeable, don't wait more than 100 ms, in any case. */
1763#define NON_WAKEABLE_POLL_TIMEOUT apr_time_from_msec(100)
1765 && (timeout < 0
1768 }
1769 else if (timeout > 0) {
1770 /* apr_pollset_poll() might round down the timeout to milliseconds,
1771 * let's forcibly round up here to never return before the timeout.
1772 */
1775 );
1776 }
1777
1779 "polling with timeout=%" APR_TIME_T_FMT
1780 " queues_timeout=%" APR_TIME_T_FMT
1781 " timers_timeout=%" APR_TIME_T_FMT,
1784
1786 if (rc != APR_SUCCESS) {
1789 "apr_pollset_poll failed. Attempting to "
1790 "shutdown process gracefully");
1792 }
1793 num = 0;
1794 }
1795
1797 now = apr_time_now();
1799 "polled with num=%u exit=%d/%d conns=%d"
1800 " queues_timeout=%" APR_TIME_T_FMT
1801 " timers_timeout=%" APR_TIME_T_FMT,
1805 }
1806
1807 /* XXX possible optimization: stash the current time for use as
1808 * r->request_time for new requests or queues maintenance
1809 */
1810
1811 for (; num; --num, ++out_pfd) {
1812 listener_poll_type *pt = (listener_poll_type *) out_pfd->client_data;
1813 if (pt->type == PT_CSD) {
1814 /* one of the sockets is readable */
1815 event_conn_state_t *cs = (event_conn_state_t *) pt->baton;
1817 /* don't wait for a worker for a keepalive request or
1818 * lingering close processing. */
1819 int blocking = 0;
1820
1821 switch (cs->pub.state) {
1823 remove_from_q = cs->sc->wc_q;
1824 blocking = 1;
1825 break;
1826
1829 remove_from_q = cs->sc->ka_q;
1830 break;
1831
1834 break;
1835
1838 break;
1839
1840 default:
1842 ap_server_conf, APLOGNO(03096)
1843 "event_loop: unexpected state %d",
1844 cs->pub.state);
1845 ap_assert(0);
1846 }
1847
1848 if (remove_from_q) {
1853 /*
1854 * Some of the pollset backends, like KQueue or Epoll
1855 * automagically remove the FD if the socket is closed,
1856 * therefore, we can accept _SUCCESS or _NOTFOUND,
1857 * and we still want to keep going
1858 */
1860 AP_DEBUG_ASSERT(0);
1862 APLOGNO(03094) "pollset remove failed");
1863 close_connection(cs);
1865 break;
1866 }
1867
1868 /* If we don't get a worker immediately (nonblocking), we
1869 * close the connection; the client can re-connect to a
1870 * different process for keepalive, and for lingering close
1871 * the connection will be shutdown so the choice is to favor
1872 * incoming/alive connections.
1873 */
1876 if (!have_idle_worker) {
1878 }
1879 else if (push2worker(cs, NULL, NULL) == APR_SUCCESS) {
1880 have_idle_worker = 0;
1881 }
1882 }
1883 }
1884 else if (pt->type == PT_ACCEPT && !listeners_disabled()) {
1885 /* A Listener Socket is ready for an accept() */
1886 if (workers_were_busy) {
1889 "All workers busy, not accepting new conns "
1890 "in this process");
1891 }
1895 "Too many open connections (%u), "
1896 "not accepting new conns in this process",
1899 "Idle workers: %u",
1901 }
1902 else if (!listener_may_exit) {
1903 void *csd = NULL;
1904 ap_listen_rec *lr = (ap_listen_rec *) pt->baton;
1905 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
1907
1908 if (ptrans == NULL) {
1909 /* create a new transaction pool for each accepted socket */
1911
1913 if (rc == APR_SUCCESS) {
1917 allocator);
1918 if (rc == APR_SUCCESS) {
1919 apr_pool_tag(ptrans, "transaction");
1921 }
1922 }
1923 if (rc != APR_SUCCESS) {
1925 ap_server_conf, APLOGNO(03097)
1926 "Failed to create transaction pool");
1927 if (allocator) {
1929 }
1932 continue;
1933 }
1934 }
1935
1937 rc = lr->accept_func(&csd, lr, ptrans);
1938
1939 /* later we trash rv and rely on csd to indicate
1940 * success/failure
1941 */
1943
1944 if (rc == APR_EGENERAL) {
1945 /* E[NM]FILE, ENOMEM, etc */
1948 }
1949
1950 if (csd != NULL) {
1953 have_idle_worker = 0;
1954 }
1955 }
1956 else {
1958 }
1959 }
1960 } /* if:else on pt->type */
1961 } /* for processing poll */
1962
1963 /* We process the timeout queues here only when the global
1964 * queues_next_expiry is passed. This happens accurately since
1965 * adding to the queues (in workers) can only decrease this expiry,
1966 * while latest ones are only taken into account here (in listener)
1967 * during queues' processing, with the lock held. This works both
1968 * with and without wake-ability.
1969 */
1970 expiry = queues_next_expiry;
1972 if (expiry && expiry < (now = apr_time_now())) {
1974 "queues maintenance with timeout=%" APR_TIME_T_FMT,
1975 expiry > 0 ? expiry - now : -1);
1977
1978 /* Steps below will recompute this. */
1980
1981 /* Step 1: keepalive timeouts */
1982 if (workers_were_busy || dying) {
1983 process_keepalive_queue(0); /* kill'em all \m/ */
1984 }
1985 else {
1987 }
1988 /* Step 2: write completion timeouts */
1991 /* Step 3: (normal) lingering close completion timeouts */
1993 /* Dying, force short timeout for normal lingering close */
1995 }
1997 /* Step 4: (short) lingering close completion timeouts */
1999
2002 "queues maintained with timeout=%" APR_TIME_T_FMT,
2004 : -1);
2005
2007 ps->write_completion = apr_atomic_read32(write_completion_q->total);
2008 ps->connections = apr_atomic_read32(&connection_count);
2009 ps->suspended = apr_atomic_read32(&suspended_count);
2010 ps->lingering_close = apr_atomic_read32(&lingering_count);
2011 }
2012 else if ((workers_were_busy || dying)
2015 process_keepalive_queue(0); /* kill'em all \m/ */
2017 ps->keep_alive = 0;
2018 }
2019
2020 /* If there are some lingering closes to defer (to a worker), schedule
2021 * them now. We might wakeup a worker spuriously if another one empties
2022 * defer_linger_chain in the meantime, but there also may be no active
2023 * or all busy workers for an undefined time. In any case a deferred
2024 * lingering close can't starve if we do that here since the chain is
2025 * filled only above in the listener and it's emptied only in the
2026 * worker(s); thus a NULL here means it will stay so while the listener
2027 * waits (possibly indefinitely) in poll().
2028 */
2029 if (defer_linger_chain) {
2032 && defer_linger_chain /* re-test */
2034 have_idle_worker = 0;
2035 }
2036 }
2037
2040 }
2041 } /* listener main loop */
2042
2044
2046 return NULL;
2047}
2048
2049/*
2050 * During graceful shutdown, if there are more running worker threads than
2051 * open connections, exit one worker thread.
2052 *
2053 * return 1 if thread should exit, 0 if it should continue running.
2054 */
2056{
2057 for (;;) {
2061
2063 if (conns >= threads_per_child - dead)
2064 return 0;
2065
2066 newdead = dead + 1;
2068 /*
2069 * No other thread has exited in the mean time, safe to exit
2070 * this one.
2071 */
2072 return 1;
2073 }
2074 }
2075}
2076
2077/* XXX For ungraceful termination/restart, we definitely don't want to
2078 * wait for active connections to finish but we may want to wait
2079 * for idle workers to get out of the queue code and release mutexes,
2080 * since those mutexes are cleaned up pretty soon and some systems
2081 * may not react favorably (i.e., segfault) if operations are attempted
2082 * on cleaned-up mutexes.
2083 */
2085{
2086 proc_info *ti = dummy;
2087 int process_slot = ti->pslot;
2088 int thread_slot = ti->tslot;
2089 apr_status_t rv;
2090 int is_idle = 0;
2091
2092 free(ti);
2093
2099
2100 for (;;) {
2104 apr_pool_t *ptrans; /* Pool for per-transaction stuff */
2105
2106 if (!is_idle) {
2108 if (rv != APR_SUCCESS) {
2110 "ap_queue_info_set_idle failed. Attempting to "
2111 "shutdown process gracefully.");
2113 break;
2114 }
2115 /* A new idler may have changed connections_above_limit(),
2116 * let the listener know and decide.
2117 */
2120 }
2121 is_idle = 1;
2122 }
2123
2126 : SERVER_READY, NULL);
2127 worker_pop:
2128 if (workers_may_exit) {
2129 break;
2130 }
2132 break;
2133 }
2134
2135 rv = ap_queue_pop_something(worker_queue, &csd, (void **)&cs,
2136 &ptrans, &te);
2137
2138 if (rv != APR_SUCCESS) {
2139 /* We get APR_EOF during a graceful shutdown once all the
2140 * connections accepted by this server process have been handled.
2141 */
2142 if (APR_STATUS_IS_EOF(rv)) {
2143 break;
2144 }
2145 /* We get APR_EINTR whenever ap_queue_pop_*() has been interrupted
2146 * from an explicit call to ap_queue_interrupt_all(). This allows
2147 * us to unblock threads stuck in ap_queue_pop_*() when a shutdown
2148 * is pending.
2149 *
2150 * If workers_may_exit is set and this is ungraceful termination/
2151 * restart, we are bound to get an error on some systems (e.g.,
2152 * AIX, which sanity-checks mutex operations) since the queue
2153 * may have already been cleaned up. Don't log the "error" if
2154 * workers_may_exit is set.
2155 */
2156 else if (APR_STATUS_IS_EINTR(rv)) {
2157 goto worker_pop;
2158 }
2159 /* We got some other error. */
2160 else if (!workers_may_exit) {
2162 APLOGNO(03099) "ap_queue_pop_socket failed");
2163 }
2164 continue;
2165 }
2166 if (te != NULL) {
2167 te->cbfunc(te->baton);
2168
2169 {
2173 }
2174 }
2175 else {
2176 is_idle = 0;
2177 if (csd != NULL) {
2181 }
2182 }
2183
2184 /* If there are deferred lingering closes, handle them now. */
2185 while (!workers_may_exit) {
2186 cs = defer_linger_chain;
2187 if (!cs) {
2188 break;
2189 }
2190 if (apr_atomic_casptr((void *)&defer_linger_chain, cs->chain,
2191 cs) != cs) {
2192 /* Race lost, try again */
2193 continue;
2194 }
2195 cs->chain = NULL;
2197
2201 }
2202 }
2203
2207
2209 return NULL;
2210}
2211
2212static int check_signal(int signum)
2213{
2214 switch (signum) {
2215 case SIGTERM:
2216 case SIGINT:
2217 return 1;
2218 }
2219 return 0;
2220}
2221
2223{
2224 int my_child_num = ts->child_num_arg;
2225 apr_threadattr_t *thread_attr = ts->threadattr;
2227 apr_status_t rv;
2228
2229 my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2231 my_info->tslot = -1; /* listener thread doesn't have a thread slot */
2232 rv = ap_thread_create(&ts->listener, thread_attr, listener_thread,
2233 my_info, pruntime);
2234 if (rv != APR_SUCCESS) {
2236 "ap_thread_create: unable to create listener thread");
2237 /* let the parent decide how bad this really is */
2239 }
2241}
2242
2243static void setup_threads_runtime(void)
2244{
2245 apr_status_t rv;
2247 apr_pool_t *pskip = NULL;
2248 int max_recycled_pools = -1, i;
2249 const int good_methods[] = { APR_POLLSET_KQUEUE,
2252 /* XXX: K-A or lingering close connection included in the async factor */
2256 (async_factor > 2 ? async_factor : 2);
2257 int pollset_flags;
2258
2259 /* Event's skiplist operations will happen concurrently with other modules'
2260 * runtime so they need their own pool for allocations, and its lifetime
2261 * should be at least the one of the connections (ptrans). Thus pskip is
2262 * created as a subpool of pconf like/before ptrans (before so that it's
2263 * destroyed after). In forked mode pconf is never destroyed so we are good
2264 * anyway, but in ONE_PROCESS mode this ensures that the skiplist works
2265 * from connection/ptrans cleanups (even after pchild is destroyed).
2266 */
2267 apr_pool_create(&pskip, pconf);
2268 apr_pool_tag(pskip, "mpm_skiplist");
2273
2274 /* All threads (listener, workers) and synchronization objects (queues,
2275 * pollset, mutexes...) created here should have at least the lifetime of
2276 * the connections they handle (i.e. ptrans). We can't use this thread's
2277 * self pool because all these objects survive it, nor use pchild or pconf
2278 * directly because this starter thread races with other modules' runtime,
2279 * nor finally pchild (or subpool thereof) because it is killed explicitly
2280 * before pconf (thus connections/ptrans can live longer, which matters in
2281 * ONE_PROCESS mode). So this leaves us with a subpool of pconf, created
2282 * before any ptrans hence destroyed after.
2283 */
2285 apr_pool_tag(pruntime, "mpm_runtime");
2286
2287 /* We must create the fd queues before we start up the listener
2288 * and worker threads. */
2290 if (rv != APR_SUCCESS) {
2292 "ap_queue_create() failed");
2294 }
2295
2297 /* If we want to conserve memory, let's not keep an unlimited number of
2298 * pools & allocators.
2299 * XXX: This should probably be a separate config directive
2300 */
2302 }
2305 if (rv != APR_SUCCESS) {
2307 "ap_queue_info_create() failed");
2309 }
2310
2311 /* Create the timeout mutex and main pollset before the listener
2312 * thread starts.
2313 */
2315 pruntime);
2316 if (rv != APR_SUCCESS) {
2318 "creation of the timeout mutex failed.");
2320 }
2321
2322 /* Create the main pollset. When APR_POLLSET_WAKEABLE is asked we account
2323 * for the wakeup pipe explicitely with pollset_size+1 because some pollset
2324 * implementations don't do it implicitely in APR.
2325 */
2328 for (i = 0; i < sizeof(good_methods) / sizeof(good_methods[0]); i++) {
2331 if (rv == APR_SUCCESS) {
2333 break;
2334 }
2335 }
2336 if (rv != APR_SUCCESS) {
2340 if (rv == APR_SUCCESS) {
2342 }
2343 else {
2347 }
2348 }
2349 if (rv != APR_SUCCESS) {
2351 "apr_pollset_create with Thread Safety failed.");
2353 }
2354
2355 /* Add listeners to the main pollset */
2357 sizeof(apr_pollfd_t));
2358 for (i = 0, lr = my_bucket->listeners; lr; lr = lr->next, i++) {
2359 apr_pollfd_t *pfd;
2361
2363 pfd = &listener_pollfd[i];
2364
2367 pfd->desc.s = lr->sd;
2368
2369 pt = apr_pcalloc(pruntime, sizeof(*pt));
2370 pfd->client_data = pt;
2371 pt->type = PT_ACCEPT;
2372 pt->baton = lr;
2373
2376
2377 lr->accept_func = ap_unixd_accept;
2378 }
2379
2381 sizeof(apr_socket_t *));
2382}
2383
2384/* XXX under some circumstances not understood, children can get stuck
2385 * in start_threads forever trying to take over slots which will
2386 * never be cleaned up; for now there is an APLOG_DEBUG message issued
2387 * every so often when this condition occurs
2388 */
2390{
2391 thread_starter *ts = dummy;
2392 apr_thread_t **threads = ts->threads;
2393 apr_threadattr_t *thread_attr = ts->threadattr;
2394 int my_child_num = ts->child_num_arg;
2396 apr_status_t rv;
2397 int threads_created = 0;
2398 int listener_started = 0;
2400 int loops, i;
2401
2403 "start_threads: Using %s (%swakeable)",
2405 listener_is_wakeable ? "" : "not ");
2406
2408 while (1) {
2409 /* threads_per_child does not include the listener thread */
2410 for (i = 0; i < threads_per_child; i++) {
2411 int status =
2413
2414 if (status != SERVER_DEAD) {
2415 continue;
2416 }
2417
2418 my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2419 my_info->pslot = my_child_num;
2420 my_info->tslot = i;
2421
2422 /* We are creating threads right now */
2425 /* We let each thread update its own scoreboard entry. This is
2426 * done because it lets us deal with tid better.
2427 */
2428 rv = ap_thread_create(&threads[i], thread_attr,
2430 if (rv != APR_SUCCESS) {
2432 APLOGNO(03104)
2433 "ap_thread_create: unable to create worker thread");
2434 /* let the parent decide how bad this really is */
2436 }
2438 }
2439
2440 /* Start the listener only when there are workers available */
2443 listener_started = 1;
2444 }
2445
2446
2448 break;
2449 }
2450 /* wait for previous generation to clean up an entry */
2452 ++loops;
2453 if (loops % 120 == 0) { /* every couple of minutes */
2456 "child %" APR_PID_T_FMT " isn't taking over "
2457 "slots very quickly (%d of %d)",
2460 }
2462 }
2463 }
2464
2465 /* What state should this child_main process be listed as in the
2466 * scoreboard...?
2467 * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
2468 * (request_rec *) NULL);
2469 *
2470 * This state should be listed separately in the scoreboard, in some kind
2471 * of process_status, not mixed in with the worker threads' status.
2472 * "life_status" is almost right, but it's in the worker's structure, and
2473 * the name could be clearer. gla
2474 */
2476 return NULL;
2477}
2478
2479static void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
2480{
2481 int i;
2483
2484 if (listener) {
2485 int iter;
2486
2487 /* deal with a rare timing window which affects waking up the
2488 * listener thread... if the signal sent to the listener thread
2489 * is delivered between the time it verifies that the
2490 * listener_may_exit flag is clear and the time it enters a
2491 * blocking syscall, the signal didn't do any good... work around
2492 * that by sleeping briefly and sending it again
2493 */
2494
2495 iter = 0;
2496 while (!dying) {
2498 if (dying || ++iter > 10) {
2499 break;
2500 }
2501 /* listener has not stopped accepting yet */
2503 "listener has not stopped accepting yet (%d iter)", iter);
2505 }
2506 if (iter > 10) {
2508 "the listener thread didn't stop accepting");
2509 }
2510 else {
2511 rv = apr_thread_join(&thread_rv, listener);
2512 if (rv != APR_SUCCESS) {
2514 "apr_thread_join: unable to join listener thread");
2515 }
2516 }
2517 }
2518
2519 for (i = 0; i < threads_per_child; i++) {
2520 if (threads[i]) { /* if we ever created this thread */
2521 rv = apr_thread_join(&thread_rv, threads[i]);
2522 if (rv != APR_SUCCESS) {
2524 "apr_thread_join: unable to join worker "
2525 "thread %d", i);
2526 }
2527 }
2528 }
2529}
2530
2532{
2534
2535 start_thread_may_exit = 1; /* tell it to give up in case it is still
2536 * trying to take over slots from a
2537 * previous generation
2538 */
2540 if (rv != APR_SUCCESS) {
2542 "apr_thread_join: unable to join the start " "thread");
2543 }
2544}
2545
2546static void child_main(int child_num_arg, int child_bucket)
2547{
2548 apr_thread_t **threads;
2549 apr_status_t rv;
2550 thread_starter *ts;
2551 apr_threadattr_t *thread_attr;
2553 int i;
2554
2555 /* for benefit of any hooks that run as this child initializes */
2556 retained->mpm->mpm_state = AP_MPMQ_STARTING;
2557
2558 ap_my_pid = getpid();
2559 ap_child_slot = child_num_arg;
2561
2562 /* Get a sub context for global allocations in this child, so that
2563 * we can have cleanups occur when the child exits.
2564 */
2566 apr_pool_tag(pchild, "pchild");
2567
2568#if AP_HAS_THREAD_LOCAL
2569 if (!one_process) {
2571 if ((rv = ap_thread_main_create(&thd, pchild))) {
2573 "Couldn't initialize child main thread");
2575 }
2576 }
2577#endif
2578
2579 /* close unused listeners and pods */
2580 for (i = 0; i < retained->mpm->num_buckets; i++) {
2581 if (i != child_bucket) {
2584 }
2585 }
2586
2587 /*stuff to do before we switch id's, so we have permissions. */
2589
2590 /* done with init critical section */
2593 }
2594
2595 /* Just use the standard apr_setup_signal_thread to block all signals
2596 * from being received. The child processes no longer use signals for
2597 * any communication with the parent process. Let's also do this before
2598 * child_init() hooks are called and possibly create threads that
2599 * otherwise could "steal" (implicitly) MPM's signals.
2600 */
2602 if (rv != APR_SUCCESS) {
2604 "Couldn't initialize signal thread");
2606 }
2607
2609
2612 }
2613 else {
2614 /* coding a value of zero means infinity */
2616 }
2617
2618 /* Setup threads */
2619
2620 /* Globals used by signal_threads() so to be initialized before */
2622
2623 /* clear the storage; we may not create all our threads immediately,
2624 * and we want a 0 entry to indicate a thread which was not created
2625 */
2626 threads = ap_calloc(threads_per_child, sizeof(apr_thread_t *));
2627 ts = apr_palloc(pchild, sizeof(*ts));
2628
2629 apr_threadattr_create(&thread_attr, pchild);
2630 /* 0 means PTHREAD_CREATE_JOINABLE */
2631 apr_threadattr_detach_set(thread_attr, 0);
2632
2633 if (ap_thread_stacksize != 0) {
2635 if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
2637 "WARNING: ThreadStackSize of %" APR_SIZE_T_FMT " is "
2638 "inappropriate, using default",
2640 }
2641 }
2642
2643 ts->threads = threads;
2644 ts->listener = NULL;
2645 ts->child_num_arg = child_num_arg;
2646 ts->threadattr = thread_attr;
2647
2649 ts, pchild);
2650 if (rv != APR_SUCCESS) {
2652 "ap_thread_create: unable to create worker thread");
2653 /* let the parent decide how bad this really is */
2655 }
2656
2657 retained->mpm->mpm_state = AP_MPMQ_RUNNING;
2658
2659 /* If we are only running in one_process mode, we will want to
2660 * still handle signals. */
2661 if (one_process) {
2662 /* Block until we get a terminating signal. */
2664 /* make sure the start thread has finished; signal_threads()
2665 * and join_workers() depend on that
2666 */
2667 /* XXX join_start_thread() won't be awakened if one of our
2668 * threads encounters a critical error and attempts to
2669 * shutdown this child
2670 */
2672
2673 /* helps us terminate a little more quickly than the dispatch of the
2674 * signal thread; beats the Pipe of Death and the browsers
2675 */
2677
2678 /* A terminating signal was received. Now join each of the
2679 * workers to clean them up.
2680 * If the worker already exited, then the join frees
2681 * their resources and returns.
2682 * If the worker hasn't exited, then this blocks until
2683 * they have (then cleans up).
2684 */
2685 join_workers(ts->listener, threads);
2686 }
2687 else { /* !one_process */
2688 /* remove SIGTERM from the set of blocked signals... if one of
2689 * the other threads in the process needs to take us down
2690 * (e.g., for MaxConnectionsPerChild) it will send us SIGTERM
2691 */
2694 /* Watch for any messages from the parent over the POD */
2695 while (1) {
2697 if (rv == AP_MPM_PODX_NORESTART) {
2698 /* see if termination was triggered while we slept */
2699 switch (terminate_mode) {
2700 case ST_GRACEFUL:
2702 break;
2703 case ST_UNGRACEFUL:
2705 break;
2706 }
2707 }
2708 if (rv == AP_MPM_PODX_GRACEFUL || rv == AP_MPM_PODX_RESTART) {
2709 /* make sure the start thread has finished;
2710 * signal_threads() and join_workers depend on that
2711 */
2713 signal_threads(rv ==
2715 break;
2716 }
2717 }
2718
2719 /* A terminating signal was received. Now join each of the
2720 * workers to clean them up.
2721 * If the worker already exited, then the join frees
2722 * their resources and returns.
2723 * If the worker hasn't exited, then this blocks until
2724 * they have (then cleans up).
2725 */
2727 "%s termination received, joining workers",
2728 rv == AP_MPM_PODX_GRACEFUL ? "graceful" : "ungraceful");
2729 join_workers(ts->listener, threads);
2731 "%s termination, workers joined, exiting",
2732 rv == AP_MPM_PODX_GRACEFUL ? "graceful" : "ungraceful");
2733 }
2734
2735 free(threads);
2736
2738}
2739
2740static int make_child(server_rec * s, int slot, int bucket)
2741{
2742 int pid;
2743
2744 if (slot + 1 > retained->max_daemon_used) {
2746 }
2747
2748 if (ap_scoreboard_image->parent[slot].pid != 0) {
2749 /* XXX replace with assert or remove ? */
2751 "BUG: Scoreboard slot %d should be empty but is "
2752 "in use by pid %" APR_PID_T_FMT,
2754 return -1;
2755 }
2756
2757 if (one_process) {
2758 my_bucket = &all_buckets[0];
2759
2761 child_main(slot, 0);
2762 /* NOTREACHED */
2763 ap_assert(0);
2764 return -1;
2765 }
2766
2767 if ((pid = fork()) == -1) {
2769 "fork: Unable to fork new process");
2770
2771 /* fork didn't succeed. There's no need to touch the scoreboard;
2772 * if we were trying to replace a failed child process, then
2773 * server_main_loop() marked its workers SERVER_DEAD, and if
2774 * we were trying to replace a child process that exited normally,
2775 * its worker_thread()s left SERVER_DEAD or SERVER_GRACEFUL behind.
2776 */
2777
2778 /* In case system resources are maxxed out, we don't want
2779 Apache running away with the CPU trying to fork over and
2780 over and over again. */
2782
2783 return -1;
2784 }
2785
2786 if (!pid) {
2787#if AP_HAS_THREAD_LOCAL
2789#endif
2790
2791 my_bucket = &all_buckets[bucket];
2792
2793#ifdef HAVE_BINDPROCESSOR
2794 /* By default, AIX binds to a single processor. This bit unbinds
2795 * children which will then bind to another CPU.
2796 */
2797 int status = bindprocessor(BINDPROCESS, (int) getpid(),
2799 if (status != OK)
2801 ap_server_conf, APLOGNO(00482)
2802 "processor unbind failed");
2803#endif
2805
2807 child_main(slot, bucket);
2808 /* NOTREACHED */
2809 ap_assert(0);
2810 return -1;
2811 }
2812
2814 return 0;
2815}
2816
2817/* start up a bunch of children */
2819{
2820 int i;
2821
2822 for (i = 0; number_to_start && i < server_limit; ++i) {
2823 if (ap_scoreboard_image->parent[i].pid != 0) {
2824 continue;
2825 }
2826 if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
2827 break;
2828 }
2830 }
2831}
2832
2834 int *max_daemon_used)
2835{
2836 int num_buckets = retained->mpm->num_buckets;
2837 int idle_thread_count = 0;
2839 int free_length = 0;
2841 int last_non_dead = -1;
2842 int active_thread_count = 0;
2843 int i, j;
2844
2845 for (i = 0; i < server_limit; ++i) {
2846 if (num_buckets > 1 && (i % num_buckets) != child_bucket) {
2847 /* We only care about child_bucket in this call */
2848 continue;
2849 }
2850 if (i >= retained->max_daemon_used &&
2852 /* short cut if all active processes have been examined and
2853 * enough empty scoreboard slots have been found
2854 */
2855 break;
2856 }
2857
2859 if (ps->pid != 0) {
2860 int child_threads_active = 0;
2861 if (ps->quiescing == 1) {
2862 ps->quiescing = 2;
2865 "Child %d quiescing: pid %d, gen %d, "
2866 "active %d/%d, total %d/%d/%d",
2867 i, (int)ps->pid, (int)ps->generation,
2870 server_limit);
2871 }
2872 for (j = 0; j < threads_per_child; j++) {
2874
2875 /* We consider a starting server as idle because we started it
2876 * at least a cycle ago, and if it still hasn't finished starting
2877 * then we're just going to swamp things worse by forking more.
2878 * So we hopefully won't need to fork more if we count it.
2879 * This depends on the ordering of SERVER_READY and SERVER_STARTING.
2880 */
2881 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
2882 && ps->generation == retained->mpm->my_generation) {
2884 }
2887 }
2888 }
2892 }
2893 last_non_dead = i;
2894 }
2897 }
2898 }
2899 if (*max_daemon_used < last_non_dead + 1) {
2900 *max_daemon_used = last_non_dead + 1;
2901 }
2902
2904 if (had_healthy_child) {
2905 /* Assume this is a transient error, even though it may not be. Leave
2906 * the server up in case it is able to serve some requests or the
2907 * problem will be resolved.
2908 */
2910 }
2911 else if (child_bucket < num_buckets - 1) {
2912 /* check for had_healthy_child up to the last child bucket */
2913 return;
2914 }
2915 else {
2916 /* looks like a basket case, as no child ever fully initialized; give up.
2917 */
2918 retained->mpm->shutdown_pending = 1;
2919 child_fatal = 1;
2921 ap_server_conf, APLOGNO(02324)
2922 "A resource shortage or other unrecoverable failure "
2923 "was encountered before any child process initialized "
2924 "successfully... httpd is exiting!");
2925 /* the child already logged the failure details */
2926 return;
2927 }
2928 }
2929
2933
2935 /*
2936 * Child processes that we ask to shut down won't die immediately
2937 * but may stay around for a long time when they finish their
2938 * requests. If the server load changes many times, many such
2939 * gracefully finishing processes may accumulate, filling up the
2940 * scoreboard. To avoid running out of scoreboard entries, we
2941 * don't shut down more processes if there are stopping ones
2942 * already (i.e. active_daemons != total_daemons) and not enough
2943 * slack space in the scoreboard for a graceful restart.
2944 *
2945 * XXX It would be nice if we could
2946 * XXX - kill processes without keepalive connections first
2947 * XXX - tell children to stop accepting new connections, and
2948 * XXX depending on server load, later be able to resurrect them
2949 * or kill them
2950 */
2955 "%shutting down one child: "
2956 "active %d/%d, total %d/%d/%d, "
2957 "idle threads %d, max workers %d",
2958 (do_kill) ? "S" : "Not s",
2962 if (do_kill) {
2965 }
2966 else {
2967 /* Wait for dying daemon(s) to exit */
2968 }
2970 }
2973 if (0 == idle_thread_count) {
2976 "server reached MaxRequestWorkers setting, "
2977 "consider raising the MaxRequestWorkers "
2978 "setting");
2980 }
2981 }
2982 else {
2985 "server is within MinSpareThreads of "
2986 "MaxRequestWorkers, consider raising the "
2987 "MaxRequestWorkers setting");
2989 }
2990 }
2992 }
2993 else if (free_length == 0) { /* scoreboard is full, can't fork */
2995 "scoreboard is full, not at MaxRequestWorkers."
2996 "Increase ServerLimit.");
2998 }
2999 else {
3002 }
3006 }
3007 else {
3009 "server is at active daemons limit, spawning "
3010 "of %d children cancelled: active %d/%d, "
3011 "total %d/%d/%d, rate %d", free_length,
3015 /* reset the spawning rate and prevent its growth below */
3018 free_length = 0;
3019 }
3020 }
3023 "server seems busy, (you may need "
3024 "to increase StartServers, ThreadsPerChild "
3025 "or Min/MaxSpareThreads), "
3026 "spawning %d children, there are around %d idle "
3027 "threads, %d active children, and %d children "
3028 "that are shutting down", free_length,
3031 }
3032 for (i = 0; i < free_length; ++i) {
3033 int slot = free_slots[i];
3035 continue;
3036 }
3037 if (*max_daemon_used < slot + 1) {
3038 *max_daemon_used = slot + 1;
3039 }
3040 }
3041 /* the next time around we want to spawn twice as many if this
3042 * wasn't good enough, but not if we've just done a graceful
3043 */
3046 }
3050 }
3051 }
3052 }
3053 else {
3055 }
3056}
3057
3059{
3060 int num_buckets = retained->mpm->num_buckets;
3061 int max_daemon_used = 0;
3062 int successive_kills = 0;
3063 int child_slot;
3066 apr_proc_t pid;
3067 int i;
3068
3069 while (!retained->mpm->restart_pending && !retained->mpm->shutdown_pending) {
3071
3072 if (pid.pid != -1) {
3076 /* fix race condition found in PR 39311
3077 * A child created at the same time as a graceful happens
3078 * can find the lock missing and create a fatal error.
3079 * It is not fatal for the last generation to be in this state.
3080 */
3081 if (child_slot < 0
3083 == retained->mpm->my_generation) {
3084 retained->mpm->shutdown_pending = 1;
3085 child_fatal = 1;
3086 /*
3087 * total_daemons counting will be off now, but as we
3088 * are shutting down, that is not an issue anymore.
3089 */
3090 return;
3091 }
3092 else {
3094 "Ignoring fatal error in child of previous "
3095 "generation (pid %ld).",
3096 (long)pid.pid);
3098 }
3099 }
3100 else if (processed_status == APEXIT_CHILDSICK) {
3101 /* tell perform_idle_server_maintenance to check into this
3102 * on the next timer pop
3103 */
3105 }
3106 /* non-fatal death... note that it's gone in the scoreboard. */
3107 if (child_slot >= 0) {
3109
3111 /* resource shortage, minimize the fork rate */
3113 }
3114 else if (remaining_children_to_start) {
3115 /* we're still doing a 1-for-1 replacement of dead
3116 * children with new children
3117 */
3121 }
3122 }
3123#if APR_HAS_OTHER_CHILD
3125 status) == 0) {
3126 /* handled */
3127 }
3128#endif
3129 else if (retained->mpm->was_graceful) {
3130 /* Great, we've probably just lost a slot in the
3131 * scoreboard. Somehow we don't know about this child.
3132 */
3134 ap_server_conf, APLOGNO(00488)
3135 "long lost child came home! (pid %ld)",
3136 (long) pid.pid);
3137 }
3138 /* Don't perform idle maintenance when a child dies,
3139 * only do it when there's a timeout. Remember only a
3140 * finite number of children can die, and it's pretty
3141 * pathological for a lot to die suddenly. If a child is
3142 * killed by a signal (faulting) we want to restart it ASAP
3143 * though, up to 3 successive faults or we stop this until
3144 * a timeout happens again (to avoid the flood of fork()ed
3145 * processes that keep being killed early).
3146 */
3148 continue;
3149 }
3150 if (++successive_kills >= 3) {
3151 if (successive_kills % 10 == 3) {
3153 ap_server_conf, APLOGNO(10392)
3154 "children are killed successively!");
3155 }
3156 continue;
3157 }
3159 }
3160 else {
3161 successive_kills = 0;
3162 }
3163
3165 /* we hit a 1 second timeout in which none of the previous
3166 * generation of children needed to be reaped... so assume
3167 * they're all done, and pick up the slack if any is left.
3168 */
3171 /* In any event we really shouldn't do the code below because
3172 * few of the servers we just started are in the IDLE state
3173 * yet, so we'd mistakenly create an extra server.
3174 */
3175 continue;
3176 }
3177
3178 max_daemon_used = 0;
3179 for (i = 0; i < num_buckets; i++) {
3180 perform_idle_server_maintenance(i, &max_daemon_used);
3181 }
3182 retained->max_daemon_used = max_daemon_used;
3183 }
3184}
3185
3187{
3188 int num_buckets = retained->mpm->num_buckets;
3190 int i;
3191
3193
3194 if (!retained->mpm->was_graceful) {
3195 if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
3196 retained->mpm->mpm_state = AP_MPMQ_STOPPING;
3197 return !OK;
3198 }
3199 /* fix the generation number in the global score; we just got a new,
3200 * cleared scoreboard
3201 */
3203 }
3204
3206
3207 /* Don't thrash since num_buckets depends on the
3208 * system and the number of online CPU cores...
3209 */
3214 /* We want to create as much children at a time as the number of buckets,
3215 * so to optimally accept connections (evenly distributed across buckets).
3216 * Thus min_spare_threads should at least maintain num_buckets children,
3217 * and max_spare_threads allow num_buckets more children w/o triggering
3218 * immediately (e.g. num_buckets idle threads margin, one per bucket).
3219 */
3224
3225 /* If we're doing a graceful_restart then we're going to see a lot
3226 * of children exiting immediately when we get into the main loop
3227 * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
3228 * rapidly... and for each one that exits we may start a new one, until
3229 * there are at least min_spare_threads idle threads, counting across
3230 * all children. But we may be permitted to start more children than
3231 * that, so we'll just keep track of how many we're
3232 * supposed to start up without the 1 second penalty between each fork.
3233 */
3237 }
3238 if (!retained->mpm->was_graceful) {
3241 }
3242 else {
3243 /* give the system some time to recover before kicking into
3244 * exponential mode */
3246 }
3247
3249 "%s configured -- resuming normal operations",
3252 "Server built: %s", ap_get_server_built());
3255
3256 retained->mpm->mpm_state = AP_MPMQ_RUNNING;
3257
3259 retained->mpm->mpm_state = AP_MPMQ_STOPPING;
3260
3261 if (retained->mpm->shutdown_pending && retained->mpm->is_ungraceful) {
3262 /* Time to shut down:
3263 * Kill child processes, tell them to call child_exit, etc...
3264 */
3265 for (i = 0; i < num_buckets; i++) {
3268 }
3269 ap_reclaim_child_processes(1, /* Start with SIGTERM */
3271
3272 if (!child_fatal) {
3273 /* cleanup pid file on normal shutdown */
3276 ap_server_conf, APLOGNO(00491) "caught SIGTERM, shutting down");
3277 }
3278
3279 return DONE;
3280 }
3281
3282 if (retained->mpm->shutdown_pending) {
3283 /* Time to gracefully shut down:
3284 * Kill child processes, tell them to call child_exit, etc...
3285 */
3286 int active_children;
3287 int index;
3288 apr_time_t cutoff = 0;
3289
3290 /* Close our listeners, and then ask our children to do same */
3292 for (i = 0; i < num_buckets; i++) {
3295 }
3297
3298 if (!child_fatal) {
3299 /* cleanup pid file on normal shutdown */
3303 ", shutting down gracefully");
3304 }
3305
3307 cutoff = apr_time_now() +
3309 }
3310
3311 /* Don't really exit until each child has finished */
3312 retained->mpm->shutdown_pending = 0;
3313 do {
3314 /* Pause for a second */
3316
3317 /* Relieve any children which have now exited */
3319
3320 active_children = 0;
3321 for (index = 0; index < retained->max_daemon_used; ++index) {
3322 if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
3323 active_children = 1;
3324 /* Having just one child is enough to stay around */
3325 break;
3326 }
3327 }
3328 } while (!retained->mpm->shutdown_pending && active_children &&
3330
3331 /* We might be here because we received SIGTERM, either
3332 * way, try and make sure that all of our processes are
3333 * really dead.
3334 */
3335 for (i = 0; i < num_buckets; i++) {
3338 }
3340
3341 return DONE;
3342 }
3343
3344 /* we've been told to restart */
3345 if (one_process) {
3346 /* not worth thinking about */
3347 return DONE;
3348 }
3349
3350 /* advance to the next generation */
3351 /* XXX: we really need to make sure this new generation number isn't in
3352 * use by any of the children.
3353 */
3354 ++retained->mpm->my_generation;
3356
3357 if (!retained->mpm->is_ungraceful) {
3359 AP_SIG_GRACEFUL_STRING " received. Doing graceful restart");
3360 /* wake up the children...time to die. But we'll have more soon */
3361 for (i = 0; i < num_buckets; i++) {
3364 }
3365
3366 /* This is mostly for debugging... so that we know what is still
3367 * gracefully dealing with existing request.
3368 */
3369
3370 }
3371 else {
3373 "SIGHUP received. Attempting to restart");
3374 /* Kill 'em all. Since the child acts the same on the parents SIGTERM
3375 * and a SIGHUP, we may as well use the same signal, because some user
3376 * pthreads are stealing signals from us left and right.
3377 */
3378 for (i = 0; i < num_buckets; i++) {
3381 }
3382
3383 ap_reclaim_child_processes(1, /* Start with SIGTERM */
3385 }
3386
3387 return OK;
3388}
3389
3390static void setup_slave_conn(conn_rec *c, void *csd)
3391{
3394
3395 mcs = ap_get_module_config(c->master->conn_config, &mpm_event_module);
3396
3397 cs = apr_pcalloc(c->pool, sizeof(*cs));
3398 cs->c = c;
3399 cs->r = NULL;
3400 cs->sc = mcs->sc;
3401 cs->suspended = 0;
3402 cs->p = c->pool;
3403 cs->bucket_alloc = c->bucket_alloc;
3404 cs->pfd = mcs->pfd;
3405 cs->pub = mcs->pub;
3408
3409 c->cs = &(cs->pub);
3410 ap_set_module_config(c->conn_config, &mpm_event_module, cs);
3411}
3412
3414{
3415 if (c->master && (!c->cs || c->cs == c->master->cs)) {
3417 }
3418 return OK;
3419}
3420
3422 const char *protocol)
3423{
3424 if (!r && s) {
3425 /* connection based switching of protocol, set the correct server
3426 * configuration, so that timeouts, keepalives and such are used
3427 * for the server that the connection was switched on.
3428 * Normally, we set this on post_read_request, but on a protocol
3429 * other than http/1.1, this might never happen.
3430 */
3432
3433 cs = ap_get_module_config(c->conn_config, &mpm_event_module);
3434 cs->sc = ap_get_module_config(s->module_config, &mpm_event_module);
3435 }
3436 return DECLINED;
3437}
3438
3439/* This really should be a post_config hook, but the error log is already
3440 * redirected by that point, so we need to do this in the open_logs phase.
3441 */
3443 apr_pool_t * ptemp, server_rec * s)
3444{
3445 int startup = 0;
3446 int level_flags = 0;
3447 int num_buckets = 0;
3449 apr_status_t rv;
3450 int i;
3451
3452 pconf = p;
3453
3454 /* the reverse of pre_config, we want this only the first time around */
3455 if (retained->mpm->module_loads == 1) {
3456 startup = 1;
3458 }
3459
3462 (startup ? NULL : s),
3463 "no listening sockets available, shutting down");
3464 return !OK;
3465 }
3466
3467 if (one_process) {
3468 num_buckets = 1;
3469 }
3470 else if (retained->mpm->was_graceful) {
3471 /* Preserve the number of buckets on graceful restarts. */
3472 num_buckets = retained->mpm->num_buckets;
3473 }
3477 (startup ? NULL : s),
3478 "could not duplicate listeners");
3479 return !OK;
3480 }
3481
3483 for (i = 0; i < num_buckets; i++) {
3484 if (!one_process && /* no POD in one_process mode */
3485 (rv = ap_mpm_podx_open(pconf, &all_buckets[i].pod))) {
3487 (startup ? NULL : s),
3488 "could not open pipe-of-death");
3489 return !OK;
3490 }
3492 }
3493
3494 if (retained->mpm->max_buckets < num_buckets) {
3495 int new_max, *new_ptr;
3496 new_max = retained->mpm->max_buckets * 2;
3497 if (new_max < num_buckets) {
3499 }
3500 new_ptr = (int *)apr_palloc(ap_pglobal, new_max * sizeof(int));
3501 if (retained->idle_spawn_rate) /* NULL at startup */
3503 retained->mpm->num_buckets * sizeof(int));
3505 retained->mpm->max_buckets = new_max;
3506 }
3507 if (retained->mpm->num_buckets < num_buckets) {
3508 int rate_max = 1;
3509 /* If new buckets are added, set their idle spawn rate to
3510 * the highest so far, so that they get filled as quickly
3511 * as the existing ones.
3512 */
3513 for (i = 0; i < retained->mpm->num_buckets; i++) {
3516 }
3517 }
3518 for (/* up to date i */; i < num_buckets; i++) {
3520 }
3521 }
3522 retained->mpm->num_buckets = num_buckets;
3523
3524 /* for skiplist */
3525 srand((unsigned int)apr_time_now());
3526 return OK;
3527}
3528
3530 apr_pool_t * ptemp)
3531{
3533 apr_status_t rv;
3534 const char *userdata_key = "mpm_event_module";
3535 int test_atomics = 0;
3536
3537 debug = ap_exists_config_define("DEBUG");
3538
3539 if (debug) {
3540 foreground = one_process = 1;
3541 no_detach = 0;
3542 }
3543 else {
3544 one_process = ap_exists_config_define("ONE_PROCESS");
3545 no_detach = ap_exists_config_define("NO_DETACH");
3546 foreground = ap_exists_config_define("FOREGROUND");
3547 }
3548
3550 if (!retained) {
3553 if (retained->mpm->module_loads) {
3554 test_atomics = 1;
3555 }
3556 }
3557 retained->mpm->mpm_state = AP_MPMQ_STARTING;
3558 if (retained->mpm->baton != retained) {
3559 retained->mpm->was_graceful = 0;
3560 retained->mpm->baton = retained;
3561 }
3562 ++retained->mpm->module_loads;
3563
3564 /* test once for correct operation of fdqueue */
3565 if (test_atomics || retained->mpm->module_loads == 2) {
3566 static apr_uint32_t foo1, foo2;
3567
3568 apr_atomic_set32(&foo1, 100);
3569 foo2 = apr_atomic_add32(&foo1, -10);
3570 if (foo2 != 100 || foo1 != 90) {
3572 "atomics not working as expected - add32 of negative number");
3574 }
3575 }
3576
3577 /* sigh, want this only the second time around */
3578 if (retained->mpm->module_loads == 2) {
3581 if (rv != APR_SUCCESS) {
3583 "Couldn't create a Thread Safe Pollset. "
3584 "Is it supported on your platform?"
3585 "Also check system or user limits!");
3587 }
3589
3590 if (!one_process && !foreground) {
3591 /* before we detach, setup crash handlers to log to errorlog */
3595 if (rv != APR_SUCCESS) {
3597 "apr_proc_detach failed");
3599 }
3600 }
3601 }
3602
3604
3617
3623
3624 return OK;
3625}
3626
3628 apr_pool_t *ptemp, server_rec *s)
3629{
3630 struct {
3631 struct timeout_queue *tail, *q;
3633 } wc, ka;
3634
3635 /* Not needed in pre_config stage */
3637 return OK;
3638 }
3639
3640 wc.tail = ka.tail = NULL;
3641 wc.hash = apr_hash_make(ptemp);
3642 ka.hash = apr_hash_make(ptemp);
3643
3645 NULL);
3647 NULL);
3648
3649 for (; s; s = s->next) {
3650 event_srv_cfg *sc = apr_pcalloc(pconf, sizeof *sc);
3651
3652 ap_set_module_config(s->module_config, &mpm_event_module, sc);
3653 if (!wc.tail) {
3654 /* The main server uses the global queues */
3655 wc.q = TO_QUEUE_MAKE(pconf, s->timeout, NULL);
3656 apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
3657 wc.tail = write_completion_q = wc.q;
3658
3659 ka.q = TO_QUEUE_MAKE(pconf, s->keep_alive_timeout, NULL);
3660 apr_hash_set(ka.hash, &s->keep_alive_timeout,
3661 sizeof s->keep_alive_timeout, ka.q);
3662 ka.tail = keepalive_q = ka.q;
3663 }
3664 else {
3665 /* The vhosts use any existing queue with the same timeout,
3666 * or their own queue(s) if there isn't */
3667 wc.q = apr_hash_get(wc.hash, &s->timeout, sizeof s->timeout);
3668 if (!wc.q) {
3669 wc.q = TO_QUEUE_MAKE(pconf, s->timeout, wc.tail);
3670 apr_hash_set(wc.hash, &s->timeout, sizeof s->timeout, wc.q);
3671 wc.tail = wc.tail->next = wc.q;
3672 }
3673
3674 ka.q = apr_hash_get(ka.hash, &s->keep_alive_timeout,
3675 sizeof s->keep_alive_timeout);
3676 if (!ka.q) {
3677 ka.q = TO_QUEUE_MAKE(pconf, s->keep_alive_timeout, ka.tail);
3678 apr_hash_set(ka.hash, &s->keep_alive_timeout,
3679 sizeof s->keep_alive_timeout, ka.q);
3680 ka.tail = ka.tail->next = ka.q;
3681 }
3682 }
3683 sc->wc_q = wc.q;
3684 sc->ka_q = ka.q;
3685 }
3686
3687 return OK;
3688}
3689
3691 apr_pool_t *ptemp, server_rec *s)
3692{
3693 int startup = 0;
3694
3695 /* the reverse of pre_config, we want this only the first time around */
3696 if (retained->mpm->module_loads == 1) {
3697 startup = 1;
3698 }
3699
3701 if (startup) {
3703 "WARNING: ServerLimit of %d exceeds compile-time "
3704 "limit of %d servers, decreasing to %d.",
3706 } else {
3708 "ServerLimit of %d exceeds compile-time limit "
3709 "of %d, decreasing to match",
3711 }
3713 }
3714 else if (server_limit < 1) {
3715 if (startup) {
3717 "WARNING: ServerLimit of %d not allowed, "
3718 "increasing to 1.", server_limit);
3719 } else {
3721 "ServerLimit of %d not allowed, increasing to 1",
3722 server_limit);
3723 }
3724 server_limit = 1;
3725 }
3726
3727 /* you cannot change ServerLimit across a restart; ignore
3728 * any such attempts
3729 */
3732 }
3734 /* don't need a startup console version here */
3736 "changing ServerLimit to %d from original value of %d "
3737 "not allowed during restart",
3740 }
3741
3743 if (startup) {
3745 "WARNING: ThreadLimit of %d exceeds compile-time "
3746 "limit of %d threads, decreasing to %d.",
3748 } else {
3750 "ThreadLimit of %d exceeds compile-time limit "
3751 "of %d, decreasing to match",
3753 }
3755 }
3756 else if (thread_limit < 1) {
3757 if (startup) {
3759 "WARNING: ThreadLimit of %d not allowed, "
3760 "increasing to 1.", thread_limit);
3761 } else {
3763 "ThreadLimit of %d not allowed, increasing to 1",
3764 thread_limit);
3765 }
3766 thread_limit = 1;
3767 }
3768
3769 /* you cannot change ThreadLimit across a restart; ignore
3770 * any such attempts
3771 */
3774 }
3776 /* don't need a startup console version here */
3778 "changing ThreadLimit to %d from original value of %d "
3779 "not allowed during restart",
3782 }
3783
3785 if (startup) {
3787 "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
3788 "of %d threads, decreasing to %d. "
3789 "To increase, please see the ThreadLimit directive.",
3791 } else {
3793 "ThreadsPerChild of %d exceeds ThreadLimit "
3794 "of %d, decreasing to match",
3796 }
3798 }
3799 else if (threads_per_child < 1) {
3800 if (startup) {
3802 "WARNING: ThreadsPerChild of %d not allowed, "
3803 "increasing to 1.", threads_per_child);
3804 } else {
3806 "ThreadsPerChild of %d not allowed, increasing to 1",
3808 }
3810 }
3811
3813 if (startup) {
3815 "WARNING: MaxRequestWorkers of %d is less than "
3816 "ThreadsPerChild of %d, increasing to %d. "
3817 "MaxRequestWorkers must be at least as large "
3818 "as the number of threads in a single server.",
3820 } else {
3822 "MaxRequestWorkers of %d is less than ThreadsPerChild "
3823 "of %d, increasing to match",
3825 }
3827 }
3828
3830
3833
3834 if (startup) {
3836 "WARNING: MaxRequestWorkers of %d is not an integer "
3837 "multiple of ThreadsPerChild of %d, decreasing to nearest "
3838 "multiple %d, for a maximum of %d servers.",
3841 } else {
3843 "MaxRequestWorkers of %d is not an integer multiple "
3844 "of ThreadsPerChild of %d, decreasing to nearest "
3845 "multiple %d", max_workers, threads_per_child,
3847 }
3849 }
3850
3852 if (startup) {
3854 "WARNING: MaxRequestWorkers of %d would require %d servers "
3855 "and would exceed ServerLimit of %d, decreasing to %d. "
3856 "To increase, please see the ServerLimit directive.",
3859 } else {
3861 "MaxRequestWorkers of %d would require %d servers and "
3862 "exceed ServerLimit of %d, decreasing to %d",
3865 }
3867 }
3868
3869 /* ap_daemons_to_start > active_daemons_limit checked in ap_mpm_run() */
3870 if (ap_daemons_to_start < 1) {
3871 if (startup) {
3873 "WARNING: StartServers of %d not allowed, "
3874 "increasing to 1.", ap_daemons_to_start);
3875 } else {
3877 "StartServers of %d not allowed, increasing to 1",
3879 }
3881 }
3882
3883 if (min_spare_threads < 1) {
3884 if (startup) {
3886 "WARNING: MinSpareThreads of %d not allowed, "
3887 "increasing to 1 to avoid almost certain server "
3888 "failure. Please read the documentation.",
3890 } else {
3892 "MinSpareThreads of %d not allowed, increasing to 1",
3894 }
3896 }
3897
3898 /* max_spare_threads < min_spare_threads + threads_per_child
3899 * checked in ap_mpm_run()
3900 */
3901
3902 return OK;
3903}
3904
3906{
3907 /* Our open_logs hook function must run before the core's, or stderr
3908 * will be redirected to a file, and the messages won't print to the
3909 * console.
3910 */
3911 static const char *const aszSucc[] = { "core.c", NULL };
3912 one_process = 0;
3913
3915 /* we need to set the MPM state before other pre-config hooks use MPM query
3916 * to retrieve it, so register as REALLY_FIRST
3917 */
3928
3931}
3932
3933static const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
3934 const char *arg)
3935{
3936 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3937 if (err != NULL) {
3938 return err;
3939 }
3940
3942 return NULL;
3943}
3944
3945static const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
3946 const char *arg)
3947{
3948 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3949 if (err != NULL) {
3950 return err;
3951 }
3952
3954 return NULL;
3955}
3956
3957static const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
3958 const char *arg)
3959{
3960 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3961 if (err != NULL) {
3962 return err;
3963 }
3964
3966 return NULL;
3967}
3968
3969static const char *set_max_workers(cmd_parms * cmd, void *dummy,
3970 const char *arg)
3971{
3972 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3973 if (err != NULL) {
3974 return err;
3975 }
3976 if (!strcasecmp(cmd->cmd->name, "MaxClients")) {
3978 "MaxClients is deprecated, use MaxRequestWorkers "
3979 "instead.");
3980 }
3981 max_workers = atoi(arg);
3982 return NULL;
3983}
3984
3985static const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
3986 const char *arg)
3987{
3988 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3989 if (err != NULL) {
3990 return err;
3991 }
3992
3994 return NULL;
3995}
3996static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
3997{
3998 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
3999 if (err != NULL) {
4000 return err;
4001 }
4002
4004 return NULL;
4005}
4006
4007static const char *set_thread_limit(cmd_parms * cmd, void *dummy,
4008 const char *arg)
4009{
4010 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
4011 if (err != NULL) {
4012 return err;
4013 }
4014
4016 return NULL;
4017}
4018
4019static const char *set_worker_factor(cmd_parms * cmd, void *dummy,
4020 const char *arg)
4021{
4022 double val;
4023 char *endptr;
4024 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
4025 if (err != NULL) {
4026 return err;
4027 }
4028
4029 val = strtod(arg, &endptr);
4030 if (*endptr)
4031 return "error parsing value";
4032
4033 if (val <= 0)
4034 return "AsyncRequestWorkerFactor argument must be a positive number";
4035
4039 }
4040 return NULL;
4041}
4042
4043
4044static const command_rec event_cmds[] = {
4047 "Number of child processes launched at server startup"),
4049 "Maximum number of child processes for this run of Apache"),
4051 "Minimum number of idle threads, to handle request spikes"),
4053 "Maximum number of idle threads"),
4055 "Deprecated name of MaxRequestWorkers"),
4056 AP_INIT_TAKE1("MaxRequestWorkers", set_max_workers, NULL, RSRC_CONF,
4057 "Maximum number of threads alive at the same time"),
4059 "Number of threads each child creates"),
4061 "Maximum number of worker threads per child process for this "
4062 "run of Apache - Upper limit for ThreadsPerChild"),
4063 AP_INIT_TAKE1("AsyncRequestWorkerFactor", set_worker_factor, NULL, RSRC_CONF,
4064 "How many additional connects will be accepted per idle "
4065 "worker thread"),
4067 {NULL}
4068};
4069
4072 NULL, /* hook to run before apache parses args */
4073 NULL, /* create per-directory config structure */
4074 NULL, /* merge per-directory config structures */
4075 NULL, /* create per-server config structure */
4076 NULL, /* merge per-server config structures */
4077 event_cmds, /* command apr_table_t */
4078 event_hooks /* register_hooks */
4079};
Symbol export macros and hook functions.
Apache Listeners Library.
Apache Multi-Processing Module library.
APR Atomic Operations.
APR File I/O Handling.
APR Poll interface.
APR Portability Routines.
Thread Safe FIFO bounded queue.
#define hash(h, r, b, n)
Definition apr_random.c:51
APR Rings.
APR Signal Handling.
APR skip list implementation.
APR Strings library.
APR Thread Mutex Routines.
APR Thread and Process Library.
APR Versioning Interface.
APR Standard Headers Support.
apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
Definition atomic.c:30
apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem)
Definition atomic.c:51
int apr_atomic_dec32(volatile apr_uint32_t *mem)
Definition atomic.c:56
void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
Definition atomic.c:73
apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t swap, apr_uint32_t cmp)
Definition atomic.c:78
apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem)
Definition atomic.c:68
int ap_start_lingering_close(conn_rec *c)
Definition connection.c:121
int ap_run_process_connection(conn_rec *c)
Definition connection.c:42
void ap_hook_pre_connection(ap_HOOK_pre_connection_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition connection.c:43
conn_rec * ap_run_create_connection(apr_pool_t *p, server_rec *server, apr_socket_t *csd, long conn_id, void *sbh, apr_bucket_alloc_t *alloc)
Definition connection.c:41
int ap_pre_connection(conn_rec *c, void *csd)
Definition core.c:5353
static apr_status_t push_timer2worker(timer_event_t *te)
Definition event.c:1308
#define DEFAULT_SERVER_LIMIT
Definition event.c:115
static int one_process
Definition event.c:435
static void *APR_THREAD_FUNC listener_thread(apr_thread_t *thd, void *dummy)
Definition event.c:1651
static int had_healthy_child
Definition event.c:173
static apr_status_t push2worker(event_conn_state_t *cs, apr_socket_t *csd, apr_pool_t *ptrans)
Definition event.c:1317
static int server_limit
Definition event.c:171
#define ST_INIT
Definition event.c:611
static void join_start_thread(apr_thread_t *start_thread_id)
Definition event.c:2531
static int worker_thread_should_exit_early(void)
Definition event.c:2055
static void startup_children(int number_to_start)
Definition event.c:2818
static apr_pool_t * pruntime
Definition event.c:443
static void close_socket_nonblocking_(apr_socket_t *csd, const char *from, int line)
Definition event.c:536
#define MAX_SPAWN_RATE
Definition event.c:402
static int event_query(int query_code, int *result, apr_status_t *rv)
Definition event.c:643
static void *APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void *dummy)
Definition event.c:2084
static int event_protocol_switch(conn_rec *c, request_rec *r, server_rec *s, const char *protocol)
Definition event.c:3421
static apr_socket_t ** worker_sockets
Definition event.c:463
static void unblock_signal(int sig)
Definition event.c:1287
static apr_pool_t * pchild
Definition event.c:442
static void server_main_loop(int remaining_children_to_start)
Definition event.c:3058
static int event_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
Definition event.c:3186
static volatile int start_thread_may_exit
Definition event.c:176
static int max_spare_threads
Definition event.c:168
static int event_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
Definition event.c:3627
static void just_die(int sig)
Definition event.c:774
static void clean_child_exit(int code) __attribute__((noreturn))
Definition event.c:756
static int child_fatal
Definition event.c:783
static event_retained_data * retained
Definition event.c:406
static apr_status_t event_request_cleanup(void *dummy)
Definition event.c:916
static volatile apr_uint32_t listensocks_disabled
Definition event.c:465
static apr_skiplist * timer_skiplist
Definition event.c:1392
static event_conn_state_t *volatile defer_linger_chain
Definition event.c:219
static void notify_suspend(event_conn_state_t *cs)
Definition event.c:820
static event_child_bucket * all_buckets
Definition event.c:412
static unsigned int worker_factor
Definition event.c:162
static apr_status_t decrement_connection_count(void *cs_)
Definition event.c:785
static struct timeout_queue * TO_QUEUE_MAKE(apr_pool_t *p, apr_time_t t, struct timeout_queue *ref)
Definition event.c:318
#define ST_UNGRACEFUL
Definition event.c:613
static int min_spare_threads
Definition event.c:167
#define MAX_SECS_TO_LINGER
Definition event.c:150
static void process_timeout_queue(struct timeout_queue *q, apr_time_t expiry, int(*func)(event_conn_state_t *))
Definition event.c:1559
static void process_lingering_close(event_conn_state_t *cs)
Definition event.c:1481
static apr_pool_t * pconf
Definition event.c:441
static apr_uint32_t threads_shutdown
Definition event.c:186
static struct timeout_queue * short_linger_q
Definition event.c:273
static void TO_QUEUE_APPEND(struct timeout_queue *q, event_conn_state_t *el)
Definition event.c:286
static void event_note_child_stopped(int slot, pid_t pid, ap_generation_t gen)
Definition event.c:699
#define MAX_SERVER_LIMIT
Definition event.c:122
static timer_event_t timer_free_ring
Definition event.c:1390
static void child_main(int child_num_arg, int child_bucket)
Definition event.c:2546
static struct timeout_queue * keepalive_q
Definition event.c:271
static void *APR_THREAD_FUNC start_threads(apr_thread_t *thd, void *dummy)
Definition event.c:2389
static apr_uint32_t lingering_count
Definition event.c:183
#define LISTENER_SIGNAL
Definition event.c:458
static void signal_threads(int mode)
Definition event.c:617
static int ap_child_slot
Definition event.c:450
static void close_connection(event_conn_state_t *cs)
Definition event.c:870
#define DEFAULT_WORKER_FACTOR
Definition event.c:159
#define NON_WAKEABLE_POLL_TIMEOUT
static int defer_lingering_close(event_conn_state_t *cs)
Definition event.c:840
#define TIMEOUT_FUDGE_FACTOR
Definition event.c:280
static apr_uint32_t clogged_count
Definition event.c:185
#define DEFAULT_THREAD_LIMIT
Definition event.c:133
static void dummy_signal_handler(int sig)
Definition event.c:1300
static const char * set_max_workers(cmd_parms *cmd, void *dummy, const char *arg)
Definition event.c:3969
static int event_open_logs(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
Definition event.c:3442
static const char * set_server_limit(cmd_parms *cmd, void *dummy, const char *arg)
Definition event.c:3996
static const char * set_min_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
Definition event.c:3945
static volatile int workers_may_exit
Definition event.c:175
static void event_note_child_started(int slot, pid_t pid)
Definition event.c:731
static apr_uint32_t suspended_count
Definition event.c:184
static int max_workers
Definition event.c:170
static int timer_comp(void *a, void *b)
Definition event.c:1413
static int event_check_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
Definition event.c:3690
static const command_rec event_cmds[]
Definition event.c:4044
static struct timeout_queue * linger_q
Definition event.c:272
static const char * set_thread_limit(cmd_parms *cmd, void *dummy, const char *arg)
Definition event.c:4007
static void enable_listensocks(void)
Definition event.c:481
static event_child_bucket * my_bucket
Definition event.c:413
static void event_pre_read_request(request_rec *r, conn_rec *c)
Definition event.c:926
poll_type_e
Definition event.c:353
@ PT_CSD
Definition event.c:354
@ PT_ACCEPT
Definition event.c:355
#define MPM_CHILD_PID(i)
Definition event.c:143
static int active_daemons_limit
Definition event.c:169
static pid_t parent_pid
Definition event.c:447
static fd_queue_t * worker_queue
Definition event.c:189
static const char * set_max_spare_threads(cmd_parms *cmd, void *dummy, const char *arg)
Definition event.c:3957
static volatile apr_time_t timers_next_expiry
Definition event.c:1393
#define close_socket_nonblocking(csd)
Definition event.c:558
static apr_thread_mutex_t * g_timer_skiplist_mtx
Definition event.c:1422
#define WORKER_FACTOR_SCALE
Definition event.c:161
#define MAX_THREAD_LIMIT
Definition event.c:140
static const char * event_get_name(void)
Definition event.c:749
#define ST_GRACEFUL
Definition event.c:612
static int shutdown_connection(event_conn_state_t *cs)
Definition event.c:885
static int event_post_read_request(request_rec *r)
Definition event.c:942
static apr_status_t ptrans_pre_cleanup(void *dummy)
Definition event.c:902
static apr_uint32_t connection_count
Definition event.c:182
static pid_t ap_my_pid
Definition event.c:445
static int num_listensocks
Definition event.c:179
#define LINGERING_BUF_SIZE
Definition event.c:1480
static int listener_is_wakeable
Definition event.c:178
static APR_INLINE int should_enable_listensocks(void)
Definition event.c:531
static apr_pollfd_t * listener_pollfd
Definition event.c:200
static fd_queue_info_t * worker_queue_info
Definition event.c:190
static apr_os_thread_t * listener_os_thread
Definition event.c:448
static volatile int listener_may_exit
Definition event.c:177
static void disable_listensocks(void)
Definition event.c:467
static void notify_resume(event_conn_state_t *cs, int cleanup)
Definition event.c:827
static struct timeout_queue * write_completion_q
Definition event.c:270
static void update_reqevents_from_sense(event_conn_state_t *cs, int sense)
Definition event.c:966
static apr_thread_mutex_t * timeout_mutex
Definition event.c:192
static const char * set_worker_factor(cmd_parms *cmd, void *dummy, const char *arg)
Definition event.c:4019
static int thread_limit
Definition event.c:172
#define TO_QUEUE_ELEM_INIT(el)
Definition event.c:331
#define SECONDS_TO_LINGER
Definition event.c:152
static apr_pollset_t * event_pollset
Definition event.c:211
static int make_child(server_rec *s, int slot, int bucket)
Definition event.c:2740
static const char * set_threads_per_child(cmd_parms *cmd, void *dummy, const char *arg)
Definition event.c:3985
static const char * set_daemons_to_start(cmd_parms *cmd, void *dummy, const char *arg)
Definition event.c:3933
static void process_socket(apr_thread_t *thd, apr_pool_t *p, apr_socket_t *sock, event_conn_state_t *cs, int my_child_num, int my_thread_num)
Definition event.c:990
static void process_keepalive_queue(apr_time_t expiry)
Definition event.c:1638
#define ID_FROM_CHILD_THREAD(c, t)
Definition event.c:420
static apr_int32_t conns_this_child
Definition event.c:180
static int close_listeners(int *closed)
Definition event.c:1259
static void setup_threads_runtime(void)
Definition event.c:2243
static int check_signal(int signum)
Definition event.c:2212
static APR_INLINE apr_uint32_t listeners_disabled(void)
Definition event.c:506
static void close_worker_sockets(void)
Definition event.c:561
static volatile int dying
Definition event.c:174
static void TO_QUEUE_REMOVE(struct timeout_queue *q, event_conn_state_t *el)
Definition event.c:310
static void create_listener_thread(thread_starter *ts)
Definition event.c:2222
#define EVENT_FUDGE_FACTOR
Definition event.c:1399
static apr_status_t event_register_timed_callback(apr_time_t t, ap_mpm_callback_fn_t *cbfn, void *baton)
Definition event.c:1424
static int ap_daemons_to_start
Definition event.c:166
static APR_INLINE int connections_above_limit(int *busy)
Definition event.c:511
static int event_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
Definition event.c:3529
static void perform_idle_server_maintenance(int child_bucket, int *max_daemon_used)
Definition event.c:2833
static void setup_slave_conn(conn_rec *c, void *csd)
Definition event.c:3390
static int resource_shortage
Definition event.c:188
static volatile apr_time_t queues_next_expiry
Definition event.c:274
static int threads_per_child
Definition event.c:165
static void join_workers(apr_thread_t *listener, apr_thread_t **threads)
Definition event.c:2479
static void wakeup_listener(void)
Definition event.c:573
static void check_infinite_requests(void)
Definition event.c:1246
static void event_hooks(apr_pool_t *p)
Definition event.c:3905
static void get_worker(int *have_idle_worker_p, int blocking, int *all_busy)
Definition event.c:1359
static int terminate_mode
Definition event.c:615
static int event_pre_connection(conn_rec *c, void *csd)
Definition event.c:3413
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
void ap_run_child_init(apr_pool_t *pchild, server_rec *s)
Definition config.c:167
void ap_hook_post_config(ap_HOOK_post_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:105
#define AP_DECLARE_MODULE(foo)
void ap_hook_open_logs(ap_HOOK_open_logs_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:163
void ap_hook_check_config(ap_HOOK_check_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:96
#define ap_set_module_config(v, m, val)
void ap_hook_pre_config(ap_HOOK_pre_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:91
void * ap_retained_data_create(const char *key, apr_size_t size)
Definition config.c:2527
const char server_rec server_rec ** ps
request_rec * r
void * ap_retained_data_get(const char *key)
Definition config.c:2519
void * csd
const char * ap_get_server_built(void)
Definition buildmark.c:26
const char * ap_get_server_description(void)
Definition core.c:3587
#define DECLINED
Definition httpd.h:457
#define APEXIT_CHILDSICK
Definition httpd.h:335
#define OK
Definition httpd.h:456
#define DONE
Definition httpd.h:458
#define APEXIT_CHILDFATAL
Definition httpd.h:341
#define AP_SQ_MS_CREATE_PRE_CONFIG
Definition http_core.h:1047
int ap_exists_config_define(const char *name)
Definition core.c:2896
int ap_state_query(int query_code)
Definition core.c:5378
#define AP_SQ_MAIN_STATE
Definition http_core.h:1030
apr_socket_t * ap_get_conn_socket(conn_rec *c)
Definition core.c:5202
void ap_close_listeners(void)
Definition listen.c:763
#define LISTEN_COMMANDS
Definition ap_listen.h:146
void ap_close_listeners_ex(ap_listen_rec *listeners)
Definition listen.c:778
void ap_listen_pre_config(void)
Definition listen.c:804
apr_status_t ap_duplicate_listeners(apr_pool_t *p, server_rec *s, ap_listen_rec ***buckets, int *num_buckets)
Definition listen.c:669
int ap_setup_listeners(server_rec *s)
Definition listen.c:610
#define APLOG_TRACE8
Definition http_log.h:79
#define APLOGNO(n)
Definition http_log.h:117
#define APLOGtrace7(s)
Definition http_log.h:241
#define APLOG_NOTICE
Definition http_log.h:69
#define APLOG_STARTUP
Definition http_log.h:105
#define APLOG_INFO
Definition http_log.h:70
#define APLOG_ERR
Definition http_log.h:67
#define APLOGtrace6(s)
Definition http_log.h:240
#define ap_log_error
Definition http_log.h:370
#define ap_log_cerror
Definition http_log.h:498
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_WARNING
Definition http_log.h:68
void ap_remove_pid(apr_pool_t *p, const char *fname)
Definition log.c:1611
#define APLOG_ALERT
Definition http_log.h:65
#define APLOG_TRACE7
Definition http_log.h:78
#define APLOG_CRIT
Definition http_log.h:66
#define APLOG_EMERG
Definition http_log.h:64
#define APLOG_TRACE1
Definition http_log.h:72
#define APLOG_TRACE5
Definition http_log.h:76
void ap_log_mpm_common(server_rec *s)
Definition log.c:1603
void ap_log_pid(apr_pool_t *p, const char *fname)
Definition log.c:1630
#define APLOG_TRACE6
Definition http_log.h:77
#define APLOG_DEBUG
Definition http_log.h:71
void ap_log_command_line(apr_pool_t *p, server_rec *s)
Definition log.c:1575
apr_pool_t * ap_pglobal
Definition config.c:63
server_rec * ap_server_conf
Definition config.c:62
void ap_run_child_status(server_rec *s, pid_t pid, ap_generation_t gen, int slot, mpm_child_status state)
Definition mpm_common.c:109
void ap_hook_mpm(ap_HOOK_mpm_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mpm_common.c:97
void() ap_mpm_callback_fn_t(void *baton)
Definition ap_mpm.h:198
@ MPM_CHILD_EXITED
Definition ap_mpm.h:207
@ MPM_CHILD_STARTED
Definition ap_mpm.h:206
void ap_hook_pre_read_request(ap_HOOK_pre_read_request_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition protocol.c:2583
void ap_hook_protocol_switch(ap_HOOK_protocol_switch_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition protocol.c:2603
void ap_hook_post_read_request(ap_HOOK_post_read_request_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition protocol.c:2585
ap_vhost_iterate_conn_cb void * baton
Definition http_vhost.h:87
void * dummy
Definition http_vhost.h:62
void const char * arg
Definition http_vhost.h:63
#define DEFAULT_MAX_FREE_DAEMON
Definition mpm_default.h:42
#define DEFAULT_MIN_FREE_DAEMON
Definition mpm_default.h:48
#define DEFAULT_START_DAEMON
Definition mpm_default.h:34
#define DEFAULT_THREADS_PER_CHILD
Definition mpm_default.h:52
#define AP_SIG_GRACEFUL_STRING
Definition mpm_common.h:73
void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret, apr_pool_t *p, server_rec *s)
Definition mpm_common.c:181
const char * ap_pid_fname
Definition mpm_common.c:150
apr_status_t ap_mpm_safe_kill(pid_t pid, int sig)
Definition mpm_unix.c:331
#define AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND
Definition mpm_common.h:369
int ap_max_requests_per_child
Definition mpm_common.c:151
#define AP_SIG_GRACEFUL_STOP_STRING
Definition mpm_common.h:82
void ap_hook_mpm_register_timed_callback(ap_HOOK_mpm_register_timed_callback_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mpm_common.c:103
void ap_run_resume_connection(conn_rec *c, request_rec *r)
Definition mpm_common.c:115
void ap_run_suspend_connection(conn_rec *c, request_rec *r)
Definition mpm_common.c:112
void ap_run_child_stopping(apr_pool_t *pchild, int graceful)
Definition mpm_common.c:118
void ap_hook_mpm_get_name(ap_HOOK_mpm_get_name_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mpm_common.c:136
void ap_relieve_child_processes(ap_reclaim_callback_fn_t *mpm_callback)
Definition mpm_unix.c:286
int ap_graceful_shutdown_timeout
Definition mpm_common.c:154
int ap_process_child_status(apr_proc_t *pid, apr_exit_why_e why, int status)
Definition mpm_unix.c:386
void ap_reclaim_child_processes(int terminate, ap_reclaim_callback_fn_t *mpm_callback)
Definition mpm_unix.c:184
apr_status_t ap_fatal_signal_child_setup(server_rec *s)
Definition mpm_unix.c:1011
void ap_hook_mpm_query(ap_HOOK_mpm_query_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition mpm_common.c:100
void ap_mpm_podx_killpg(ap_pod_t *pod, int num, ap_podx_restart_t graceful)
Definition mpm_unix.c:609
apr_size_t ap_thread_stacksize
Definition mpm_common.c:156
apr_uint32_t ap_max_mem_free
Definition mpm_common.c:155
apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf)
Definition mpm_unix.c:1044
int ap_mpm_podx_check(ap_pod_t *pod)
Definition mpm_unix.c:540
apr_status_t ap_mpm_podx_signal(ap_pod_t *pod, ap_podx_restart_t graceful)
Definition mpm_unix.c:603
apr_status_t ap_mpm_podx_close(ap_pod_t *pod)
Definition mpm_unix.c:562
int ap_run_drop_privileges(apr_pool_t *pchild, server_rec *s)
Definition mpm_common.c:94
apr_status_t ap_mpm_podx_open(apr_pool_t *p, ap_pod_t **pod)
Definition mpm_unix.c:519
@ AP_MPM_PODX_NORESTART
Definition mpm_common.h:284
@ AP_MPM_PODX_RESTART
Definition mpm_common.h:284
@ AP_MPM_PODX_GRACEFUL
Definition mpm_common.h:284
#define APR_EAGAIN
Definition apr_errno.h:730
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_ENOTIMPL
Definition apr_errno.h:476
unsigned int count
Definition apr_md5.h:152
#define APR_OC_REASON_DEATH
#define APR_STATUS_IS_EINTR(s)
Definition apr_errno.h:1281
#define APR_STATUS_IS_EEXIST(s)
Definition apr_errno.h:1233
#define APR_STATUS_IS_NOTFOUND(s)
Definition apr_errno.h:574
#define APR_STATUS_IS_TIMEUP(s)
Definition apr_errno.h:534
#define APR_STATUS_IS_EAGAIN(s)
Definition apr_errno.h:1272
#define APR_STATUS_IS_EOF(s)
Definition apr_errno.h:567
apr_bucket apr_bucket_brigade * a
apr_file_t * fd
apr_dbd_transaction_t int mode
Definition apr_dbd.h:261
const char *const const char *const * aszSucc
Definition apr_hooks.h:346
#define APR_HOOK_REALLY_FIRST
Definition apr_hooks.h:299
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
apr_redis_t * rc
Definition apr_redis.h:173
#define RSRC_CONF
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define MPM20_MODULE_STUFF
#define AP_DEBUG_ASSERT(exp)
Definition httpd.h:2283
void * ap_calloc(size_t nelem, size_t size) __attribute__((malloc))
Definition util.c:3160
#define ap_assert(exp)
Definition httpd.h:2271
void * ap_malloc(size_t size) __attribute__((malloc))
Definition util.c:3152
@ AP_CONN_KEEPALIVE
Definition httpd.h:1146
@ CONN_STATE_NUM
Definition httpd.h:1268
@ CONN_STATE_LINGER
Definition httpd.h:1264
@ CONN_STATE_LINGER_NORMAL
Definition httpd.h:1265
@ CONN_STATE_READ_REQUEST_LINE
Definition httpd.h:1260
@ CONN_STATE_LINGER_SHORT
Definition httpd.h:1266
@ CONN_STATE_CHECK_REQUEST_LINE_READABLE
Definition httpd.h:1259
@ CONN_STATE_WRITE_COMPLETION
Definition httpd.h:1262
@ CONN_STATE_SUSPENDED
Definition httpd.h:1263
@ CONN_SENSE_DEFAULT
Definition httpd.h:1272
@ CONN_SENSE_WANT_READ
Definition httpd.h:1273
#define GLOBAL_ONLY
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
#define APR_ALLOCATOR_MAX_FREE_UNLIMITED
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void apr_size_t * nbytes
void const char apr_status_t(* cleanup)(void *))
apr_file_t apr_int32_t blocking
apr_array_header_t ** result
int strcasecmp(const char *a, const char *b)
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_socket_t * sock
apr_interval_time_t t
int int int protocol
apr_interval_time_t apr_int32_t * num
Definition apr_poll.h:273
apr_interval_time_t apr_pollcb_cb_t func
Definition apr_poll.h:422
@ APR_POLL_SOCKET
Definition apr_poll.h:93
@ APR_POLLSET_EPOLL
Definition apr_poll.h:85
@ APR_POLLSET_KQUEUE
Definition apr_poll.h:83
@ APR_POLLSET_PORT
Definition apr_poll.h:84
apr_pool_t * b
Definition apr_pools.h:529
apr_abortfunc_t apr_allocator_t * allocator
Definition apr_pools.h:208
const char apr_status_t(*) apr_pool_t *poo __attribute__)((nonnull(2, 4)))
Definition apr_pools.h:567
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
int apr_os_sock_t
#define APR_RING_ENTRY(elem)
Definition apr_ring.h:70
#define APR_RING_UNSPLICE(ep1, epN, link)
Definition apr_ring.h:368
#define APR_RING_INSERT_TAIL(hp, nep, elem, link)
Definition apr_ring.h:328
#define APR_RING_INIT(hp, elem, link)
Definition apr_ring.h:192
#define APR_RING_HEAD(head, elem)
Definition apr_ring.h:91
#define APR_RING_SPLICE_TAIL(hp, ep1, epN, elem, link)
Definition apr_ring.h:302
#define APR_RING_SENTINEL(hp, elem, link)
Definition apr_ring.h:159
#define APR_RING_EMPTY(hp, elem, link)
Definition apr_ring.h:204
#define APR_RING_REMOVE(ep, link)
Definition apr_ring.h:381
#define APR_RING_FIRST(hp)
Definition apr_ring.h:166
#define APR_RING_NEXT(ep, link)
Definition apr_ring.h:177
#define APR_RING_ELEM_INIT(ep, link)
Definition apr_ring.h:212
#define apr_signal(a, b)
Definition apr_signal.h:71
void apr_skiplistnode ** iter
#define APR_INCOMPLETE_READ
#define APR_SO_NONBLOCK
const char char ** last
const char * s
Definition apr_strings.h:95
const apr_array_header_t * first
Definition apr_tables.h:207
apr_int32_t apr_int32_t apr_int32_t err
int sig
int apr_exit_why_e * exitwhy
apr_cmdtype_e cmd
#define APR_PROC_CHECK_SIGNALED(x)
#define APR_PROC_DETACH_DAEMONIZE
#define APR_PROC_DETACH_FOREGROUND
apr_exit_why_e
int int status
#define apr_time_as_msec(time)
Definition apr_time.h:72
#define apr_time_from_msec(msec)
Definition apr_time.h:75
#define APR_TIME_T_FMT
Definition apr_time.h:52
apr_int64_t apr_interval_time_t
Definition apr_time.h:55
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_from_sec(sec)
Definition apr_time.h:78
#define APR_POLLSET_NOCOPY
Definition apr_poll.h:65
#define APR_POLLSET_WAKEABLE
Definition apr_poll.h:68
#define APR_POLLSET_NODEFAULT
Definition apr_poll.h:71
#define APR_POLLSET_THREADSAFE
Definition apr_poll.h:62
#define APR_POLLERR
Definition apr_poll.h:52
#define APR_POLLOUT
Definition apr_poll.h:51
#define APR_POLLIN
Definition apr_poll.h:49
#define APR_POLLHUP
Definition apr_poll.h:53
#define AP_MPMQ_IS_FORKED
Definition ap_mpm.h:154
#define AP_MPMQ_MPM_STATE
Definition ap_mpm.h:174
#define AP_MPMQ_MAX_DAEMON_USED
Definition ap_mpm.h:150
#define AP_MPMQ_IS_ASYNC
Definition ap_mpm.h:176
#define AP_MPMQ_MAX_SPARE_DAEMONS
Definition ap_mpm.h:166
#define AP_MPMQ_MIN_SPARE_THREADS
Definition ap_mpm.h:164
#define AP_MPMQ_HARD_LIMIT_THREADS
Definition ap_mpm.h:158
#define AP_MPMQ_IS_THREADED
Definition ap_mpm.h:152
#define AP_MPMQ_MAX_THREADS
Definition ap_mpm.h:160
#define AP_MPMQ_MAX_REQUESTS_DAEMON
Definition ap_mpm.h:170
#define AP_MPMQ_MAX_SPARE_THREADS
Definition ap_mpm.h:168
#define AP_MPMQ_GENERATION
Definition ap_mpm.h:178
#define AP_MPMQ_MAX_DAEMONS
Definition ap_mpm.h:172
#define AP_MPMQ_HARD_LIMIT_DAEMONS
Definition ap_mpm.h:156
#define AP_MPMQ_MIN_SPARE_DAEMONS
Definition ap_mpm.h:162
#define AP_MPMQ_STARTING
Definition ap_mpm.h:140
#define AP_MPMQ_RUNNING
Definition ap_mpm.h:141
#define AP_MPMQ_STOPPING
Definition ap_mpm.h:142
#define RAISE_SIGSTOP(x)
Definition httpd.h:2312
#define AP_MPMQ_DYNAMIC
Definition ap_mpm.h:131
#define AP_MPMQ_STATIC
Definition ap_mpm.h:128
Apache Configuration.
Apache connection library.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP protocol handling.
Virtual Host package.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
static unsigned long num_buckets
#define debug(stmt)
Definition mod_macro.c:43
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
Multi-Processing Modules functions.
fd queue declarations
static int idle_spawn_rate
static int child_slot
apr_status_t apr_proc_detach(int daemonize)
Definition procsup.c:19
apr_status_t apr_thread_exit(apr_thread_t *thd, apr_status_t retval)
Definition thread.c:157
apr_os_thread_t apr_os_thread_current()
Definition thread.c:142
apr_status_t apr_thread_join(apr_status_t *retval, apr_thread_t *thd)
Definition thread.c:166
apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on)
Definition thread.c:41
apr_status_t apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool)
Definition thread.c:24
static int my_child_num
Definition prefork.c:154
Apache scoreboard library.
void ap_create_sb_handle(ap_sb_handle_t **new_sbh, apr_pool_t *p, int child_num, int thread_num)
Definition scoreboard.c:432
int ap_run_pre_mpm(apr_pool_t *p, ap_scoreboard_e sb_type)
Definition scoreboard.c:102
#define SERVER_STARTING
Definition scoreboard.h:57
void ap_update_sb_handle(ap_sb_handle_t *sbh, int child_num, int thread_num)
Definition scoreboard.c:425
int ap_generation_t
Definition scoreboard.h:78
#define SERVER_BUSY_WRITE
Definition scoreboard.h:60
scoreboard * ap_scoreboard_image
Definition scoreboard.c:44
int ap_extended_status
Definition scoreboard.c:61
apr_status_t ap_reopen_scoreboard(apr_pool_t *p, apr_shm_t **shm, int detached)
Definition scoreboard.c:263
int ap_update_child_status(ap_sb_handle_t *sbh, int status, request_rec *r)
Definition scoreboard.c:590
@ SB_SHARED
Definition scoreboard.h:85
#define SERVER_GRACEFUL
Definition scoreboard.h:65
#define SERVER_DEAD
Definition scoreboard.h:56
int ap_update_child_status_from_indexes(int child_num, int thread_num, int status, request_rec *r)
Definition scoreboard.c:575
#define SERVER_BUSY_KEEPALIVE
Definition scoreboard.h:61
int ap_find_child_by_pid(apr_proc_t *pid)
Definition scoreboard.c:409
#define SERVER_READY
Definition scoreboard.h:58
process_score * ap_get_scoreboard_process(int x)
Definition scoreboard.c:702
The representation of a filter chain.
Apache's listeners record.
Definition ap_listen.h:47
void * client_data
Definition apr_poll.h:114
apr_int16_t reqevents
Definition apr_poll.h:111
apr_datatype_e desc_type
Definition apr_poll.h:110
apr_descriptor desc
Definition apr_poll.h:113
Structure to store things which are per connection.
Definition httpd.h:1152
apr_table_t * notes
Definition httpd.h:1193
void * sbh
Definition httpd.h:1199
A structure to contain connection state information.
Definition httpd.h:1280
conn_state_e state
Definition httpd.h:1282
conn_sense_e sense
Definition httpd.h:1284
ap_pod_t * pod
Definition event.c:409
ap_listen_rec * listeners
Definition event.c:410
apr_bucket_alloc_t * bucket_alloc
Definition event.c:242
conn_rec * c
Definition event.c:227
struct event_conn_state_t * chain
Definition event.c:248
event_srv_cfg * sc
Definition event.c:231
apr_pollfd_t pfd
Definition event.c:244
conn_state_t pub
Definition event.c:246
ap_sb_handle_t * sbh
Definition event.c:233
apr_pool_t * p
Definition event.c:240
struct event_conn_state_t::@46 timeout_list
apr_time_t queue_timestamp
Definition event.c:225
request_rec * r
Definition event.c:229
ap_unixd_mpm_retained_data * mpm
Definition event.c:369
int hold_off_on_exponential_spawning
Definition event.c:404
int sick_child_detected
Definition event.c:373
int maxclients_reported
Definition event.c:374
int * idle_spawn_rate
Definition event.c:400
int near_maxclients_reported
Definition event.c:375
struct timeout_queue * ka_q
Definition event.c:417
struct timeout_queue * wc_q
Definition event.c:416
ap_generation_t running_generation
Definition scoreboard.h:126
poll_type_e type
Definition event.c:360
int tslot
Definition event.c:338
int pslot
Definition event.c:337
ap_generation_t generation
Definition scoreboard.h:139
A structure that represents the current request.
Definition httpd.h:845
apr_pool_t * pool
Definition httpd.h:847
conn_rec * connection
Definition httpd.h:849
server_rec * server
Definition httpd.h:851
worker_score ** servers
Definition scoreboard.h:163
process_score * parent
Definition scoreboard.h:162
global_score * global
Definition scoreboard.h:161
A structure to store information for each virtual server.
Definition httpd.h:1322
int keep_alive
Definition httpd.h:1378
struct ap_conf_vector_t * module_config
Definition httpd.h:1341
unsigned int keep_alive_timeout_set
Definition httpd.h:1403
apr_threadattr_t * threadattr
Definition event.c:349
apr_thread_t ** threads
Definition event.c:346
int child_num_arg
Definition event.c:348
apr_thread_t * listener
Definition event.c:347
struct timeout_queue * next
Definition event.c:260
struct timeout_head_t head
Definition event.c:256
apr_uint32_t * total
Definition event.c:259
apr_interval_time_t timeout
Definition event.c:257
apr_uint32_t count
Definition event.c:258
unsigned char status
Definition scoreboard.h:102
ap_generation_t generation
Definition scoreboard.h:101
static apr_table_t * t1
Definition testtable.c:34
static apr_time_t now
Definition testtime.c:33
apr_socket_t * s
Definition apr_poll.h:101
apr_status_t apr_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len)
Definition sendrecv.c:70
apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock)
Definition sockets.c:506
apr_status_t apr_socket_close(apr_socket_t *thesocket)
Definition sockets.c:211
apr_status_t apr_socket_opt_set(apr_socket_t *sock, apr_int32_t opt, apr_int32_t on)
Definition sockopt.c:113
apr_status_t apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
Definition sockopt.c:75
void ap_update_vhost_given_ip(conn_rec *conn)
Definition vhost.c:1280
IN ULONG IN INT timeout
Worker MPM defaults.