event.c revision f6aa8572a3986fcc2cfed30ce1730aca0c14df72
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * applicable.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Licensed under the Apache License, Version 2.0 (the "License");
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * you may not use this file except in compliance with the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * You may obtain a copy of the License at
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * http://www.apache.org/licenses/LICENSE-2.0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Unless required by applicable law or agreed to in writing, software
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * distributed under the License is distributed on an "AS IS" BASIS,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * See the License for the specific language governing permissions and
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * limitations under the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/**
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * This MPM tries to fix the 'keep alive problem' in HTTP.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * After a client completes the first request, the client can keep the
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * connection open to send more requests with the same socket. This can save
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * signifigant overhead in creating TCP connections. However, the major
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * disadvantage is that Apache traditionally keeps an entire child
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * process/thread waiting for data from the client. To solve this problem,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * this MPM has a dedicated thread for handling both the Listenting sockets,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * and all sockets that are in a Keep Alive status.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * The MPM assumes the underlying apr_pollset implmentation is somewhat
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * threadsafe. This currently is only compatible with KQueue and EPoll. This
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * enables the MPM to avoid extra high level locking or having to wake up the
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * listener thread when a keep-alive socket needs to be sent to it.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * This MPM not preform well on older platforms that do not have very good
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * threading, like Linux with a 2.4 kernel, but this does not matter, since we
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * require EPoll or KQueue.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * For FreeBSD, use 5.3. It is possible to run this MPM on FreeBSD 5.2.1, if
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * you use libkse (see `man libmap.conf`).
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * For NetBSD, use at least 2.0.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * For Linux, you should use a 2.6 kernel, and make sure your glibc has epoll
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * support compiled in.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_portable.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_strings.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_file_io.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_thread_proc.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_signal.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_thread_mutex.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "apr_proc_mutex.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "apr_poll.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_ring.h"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein#include "apr_queue.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define APR_WANT_STRFUNC
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "apr_want.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if APR_HAVE_UNISTD_H
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <unistd.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if APR_HAVE_SYS_SOCKET_H
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <sys/socket.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if APR_HAVE_SYS_WAIT_H
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <sys/wait.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAVE_SYS_PROCESSOR_H
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <sys/processor.h> /* for bindprocessor() */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#if !APR_HAS_THREADS
f4c310fd2555c6faca1f980f00b161eadb089023gstein#error The Event MPM requires APR threads, but they are unavailable.
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define CORE_PRIVATE
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "ap_config.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "httpd.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_main.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_log.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_config.h" /* for read_config */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_core.h" /* for get_remote_host */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_connection.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "ap_mpm.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "pod.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "mpm_common.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "ap_listen.h"
8a46775d163c06a8c51d1b0a3f2edfde945cb1d8stoddard#include "scoreboard.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "fdqueue.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "mpm_default.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_vhost.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <signal.h>
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include <limits.h> /* for INT_MAX */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Limit on the total --- clients will be locked out if more servers than
f4c310fd2555c6faca1f980f00b161eadb089023gstein * this are needed. It is intended solely to keep the server from crashing
f4c310fd2555c6faca1f980f00b161eadb089023gstein * when things get out of hand.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * We keep a hard maximum number of servers, for two reasons --- first off,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * in case something goes seriously wrong, we want to stop the fork bomb
f4c310fd2555c6faca1f980f00b161eadb089023gstein * short of actually crashing the machine we're running on by filling some
f4c310fd2555c6faca1f980f00b161eadb089023gstein * kernel table. Secondly, it keeps the size of the scoreboard file small
f4c310fd2555c6faca1f980f00b161eadb089023gstein * enough that we can read the whole thing without worrying too much about
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the overhead.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef DEFAULT_SERVER_LIMIT
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define DEFAULT_SERVER_LIMIT 16
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want
f4c310fd2555c6faca1f980f00b161eadb089023gstein * some sort of compile-time limit to help catch typos.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef MAX_SERVER_LIMIT
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define MAX_SERVER_LIMIT 20000
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Limit on the threads per process. Clients will be locked out if more than
f4c310fd2555c6faca1f980f00b161eadb089023gstein * this are needed.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * We keep this for one reason it keeps the size of the scoreboard file small
f4c310fd2555c6faca1f980f00b161eadb089023gstein * enough that we can read the whole thing without worrying too much about
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the overhead.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef DEFAULT_THREAD_LIMIT
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#define DEFAULT_THREAD_LIMIT 64
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT. We want
f4c310fd2555c6faca1f980f00b161eadb089023gstein * some sort of compile-time limit to help catch typos.
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef MAX_THREAD_LIMIT
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define MAX_THREAD_LIMIT 100000
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Actual definitions of config globals
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinint ap_threads_per_child = 0; /* Worker threads per child */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int ap_daemons_to_start = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int min_spare_threads = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int max_spare_threads = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int ap_daemons_limit = 0;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic int server_limit = DEFAULT_SERVER_LIMIT;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int first_server_limit = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int thread_limit = DEFAULT_THREAD_LIMIT;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int first_thread_limit = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int changed_limit_at_restart;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic int dying = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int workers_may_exit = 0;
fe4d394397840dd4823e3d6fc5affc1ab395e161gsteinstatic int start_thread_may_exit = 0;
fe4d394397840dd4823e3d6fc5affc1ab395e161gsteinstatic int listener_may_exit = 0;
fe4d394397840dd4823e3d6fc5affc1ab395e161gsteinstatic int requests_this_child;
fe4d394397840dd4823e3d6fc5affc1ab395e161gsteinstatic int num_listensocks = 0;
fe4d394397840dd4823e3d6fc5affc1ab395e161gsteinstatic int resource_shortage = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic fd_queue_t *worker_queue;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic fd_queue_info_t *worker_queue_info;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int mpm_state = AP_MPMQ_STARTING;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int sick_child_detected;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmapr_thread_mutex_t *timeout_mutex;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPR_RING_HEAD(timeout_head_t, conn_state_t);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic struct timeout_head_t timeout_head;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_pollset_t *event_pollset;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* The structure used to pass unique initialization info to each thread */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmtypedef struct
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int pid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int tid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int sd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein} proc_info;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* Structure used to pass information to the thread responsible for
f4c310fd2555c6faca1f980f00b161eadb089023gstein * creating the rest of the threads.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmtypedef struct
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_t **threads;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_t *listener;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int child_num_arg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_threadattr_t *threadattr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein} thread_starter;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteintypedef enum
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein PT_CSD,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm PT_ACCEPT
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm} poll_type_e;
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe
f4c310fd2555c6faca1f980f00b161eadb089023gsteintypedef struct
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein poll_type_e type;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int status; /*XXX what is this for? 0 and 1 don't make it clear */
f4c310fd2555c6faca1f980f00b161eadb089023gstein void *baton;
f4c310fd2555c6faca1f980f00b161eadb089023gstein} listener_poll_type;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define ID_FROM_CHILD_THREAD(c, t) ((c * thread_limit) + t)
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * The max child slot ever assigned, preserved across restarts. Necessary
f4c310fd2555c6faca1f980f00b161eadb089023gstein * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We
f4c310fd2555c6faca1f980f00b161eadb089023gstein * use this value to optimize routines that have to scan the entire
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * scoreboard.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinint ap_max_daemons_limit = -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic ap_pod_t *pod;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* *Non*-shared http_main globals... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
709df1e1c2e1710570f8cb4209497e88662829c3gsteinserver_rec *ap_server_conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
709df1e1c2e1710570f8cb4209497e88662829c3gstein/* The worker MPM respects a couple of runtime flags that can aid
709df1e1c2e1710570f8cb4209497e88662829c3gstein * in debugging. Setting the -DNO_DETACH flag will prevent the root process
f4c310fd2555c6faca1f980f00b161eadb089023gstein * from detaching from its controlling terminal. Additionally, setting
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * the -DONE_PROCESS flag (which implies -DNO_DETACH) will get you the
709df1e1c2e1710570f8cb4209497e88662829c3gstein * child_main loop running in the process which originally started up.
709df1e1c2e1710570f8cb4209497e88662829c3gstein * This gives you a pretty nice debugging environment. (You'll get a SIGHUP
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * early in standalone_main; just continue through. This is the server
709df1e1c2e1710570f8cb4209497e88662829c3gstein * trying to kill off any child processes which it might have lying
709df1e1c2e1710570f8cb4209497e88662829c3gstein * around --- Apache doesn't keep track of their pids, it just sends
709df1e1c2e1710570f8cb4209497e88662829c3gstein * SIGHUP to the process group, ignoring it in the root process.
709df1e1c2e1710570f8cb4209497e88662829c3gstein * Continue through and you'll be fine.).
709df1e1c2e1710570f8cb4209497e88662829c3gstein */
709df1e1c2e1710570f8cb4209497e88662829c3gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int one_process = 0;
709df1e1c2e1710570f8cb4209497e88662829c3gstein
709df1e1c2e1710570f8cb4209497e88662829c3gstein#ifdef DEBUG_SIGSTOP
709df1e1c2e1710570f8cb4209497e88662829c3gsteinint raise_sigstop_flags;
709df1e1c2e1710570f8cb4209497e88662829c3gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic apr_pool_t *pconf; /* Pool for config stuff */
709df1e1c2e1710570f8cb4209497e88662829c3gsteinstatic apr_pool_t *pchild; /* Pool for httpd child stuff */
709df1e1c2e1710570f8cb4209497e88662829c3gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic pid_t ap_my_pid; /* Linux getpid() doesn't work except in main
709df1e1c2e1710570f8cb4209497e88662829c3gstein thread. Use this instead */
709df1e1c2e1710570f8cb4209497e88662829c3gsteinstatic pid_t parent_pid;
709df1e1c2e1710570f8cb4209497e88662829c3gsteinstatic apr_os_thread_t *listener_os_thread;
709df1e1c2e1710570f8cb4209497e88662829c3gstein
709df1e1c2e1710570f8cb4209497e88662829c3gstein/* The LISTENER_SIGNAL signal will be sent from the main thread to the
709df1e1c2e1710570f8cb4209497e88662829c3gstein * listener thread to wake it up for graceful termination (what a child
f4c310fd2555c6faca1f980f00b161eadb089023gstein * process from an old generation does when the admin does "apachectl
709df1e1c2e1710570f8cb4209497e88662829c3gstein * graceful"). This signal will be blocked in all threads of a child
709df1e1c2e1710570f8cb4209497e88662829c3gstein * process except for the listener thread.
709df1e1c2e1710570f8cb4209497e88662829c3gstein */
709df1e1c2e1710570f8cb4209497e88662829c3gstein#define LISTENER_SIGNAL SIGHUP
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* An array of socket descriptors in use by each thread used to
709df1e1c2e1710570f8cb4209497e88662829c3gstein * perform a non-graceful (forced) shutdown of the server.
709df1e1c2e1710570f8cb4209497e88662829c3gstein */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic apr_socket_t **worker_sockets;
709df1e1c2e1710570f8cb4209497e88662829c3gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void close_worker_sockets(void)
709df1e1c2e1710570f8cb4209497e88662829c3gstein{
709df1e1c2e1710570f8cb4209497e88662829c3gstein int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < ap_threads_per_child; i++) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (worker_sockets[i]) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_socket_close(worker_sockets[i]);
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_sockets[i] = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void wakeup_listener(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein listener_may_exit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!listener_os_thread) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX there is an obscure path that this doesn't handle perfectly:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * right after listener thread is created but before
f4c310fd2555c6faca1f980f00b161eadb089023gstein * listener_os_thread is set, the first worker thread hits an
f4c310fd2555c6faca1f980f00b161eadb089023gstein * error and starts graceful termination
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * we should just be able to "kill(ap_my_pid, LISTENER_SIGNAL)" on all
f4c310fd2555c6faca1f980f00b161eadb089023gstein * platforms and wake up the listener thread since it is the only thread
f4c310fd2555c6faca1f980f00b161eadb089023gstein * with SIGHUP unblocked, but that doesn't work on Linux
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAVE_PTHREAD_KILL
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_kill(*listener_os_thread, LISTENER_SIGNAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein kill(ap_my_pid, LISTENER_SIGNAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define ST_INIT 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define ST_GRACEFUL 1
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define ST_UNGRACEFUL 2
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int terminate_mode = ST_INIT;
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void signal_threads(int mode)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (terminate_mode == mode) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein terminate_mode = mode;
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_STOPPING;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* in case we weren't called from the listener thread, wake up the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * listener thread
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein wakeup_listener();
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* for ungraceful termination, let the workers exit now;
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein * for graceful termination, the listener thread will notify the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * workers to exit once it has stopped accepting new connections
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (mode == ST_UNGRACEFUL) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm workers_may_exit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_queue_interrupt_all(worker_queue);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_queue_info_term(worker_queue_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein close_worker_sockets(); /* forcefully kill all current connections */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (query_code) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MAX_DAEMON_USED:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = ap_max_daemons_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_IS_THREADED:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = AP_MPMQ_STATIC;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_IS_FORKED:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = AP_MPMQ_DYNAMIC;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_IS_ASYNC:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_HARD_LIMIT_DAEMONS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = server_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_HARD_LIMIT_THREADS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = thread_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MAX_THREADS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = ap_threads_per_child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MIN_SPARE_DAEMONS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MIN_SPARE_THREADS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = min_spare_threads;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MAX_SPARE_DAEMONS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MAX_SPARE_THREADS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = max_spare_threads;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MAX_REQUESTS_DAEMON:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = ap_max_requests_per_child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MAX_DAEMONS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = ap_daemons_limit;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case AP_MPMQ_MPM_STATE:
f4c310fd2555c6faca1f980f00b161eadb089023gstein *result = mpm_state;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein return APR_ENOTIMPL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* a clean exit from a child with proper cleanup */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void clean_child_exit(int code) __attribute__ ((noreturn));
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void clean_child_exit(int code)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_STOPPING;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pchild) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein apr_pool_destroy(pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein exit(code);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void just_die(int sig)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*****************************************************************
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Connection structures and accounting...
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* volatile just in case */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int volatile shutdown_pending;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int volatile restart_pending;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int volatile is_graceful;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic volatile int child_fatal;
f4c310fd2555c6faca1f980f00b161eadb089023gsteinap_generation_t volatile ap_my_generation;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein * functions to initiate shutdown or restart without relying on signals.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Previously this was initiated in sig_term() and restart() signal handlers,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * but we want to be able to start a shutdown/restart from other sources --
f4c310fd2555c6faca1f980f00b161eadb089023gstein * e.g. on Win32, from the service manager. Now the service manager can
f4c310fd2555c6faca1f980f00b161eadb089023gstein * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
f4c310fd2555c6faca1f980f00b161eadb089023gstein * these functions can also be called by the child processes, since global
f4c310fd2555c6faca1f980f00b161eadb089023gstein * variables are no longer used to pass on the required action to the parent.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein * These should only be called from the parent process itself, since the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * parent process will use the shutdown_pending and restart_pending variables
f4c310fd2555c6faca1f980f00b161eadb089023gstein * to determine whether to shutdown or restart. The child process should
f4c310fd2555c6faca1f980f00b161eadb089023gstein * call signal_parent() directly to tell the parent to die -- this will
f4c310fd2555c6faca1f980f00b161eadb089023gstein * cause neither of those variable to be set, which the parent will
f4c310fd2555c6faca1f980f00b161eadb089023gstein * assume means something serious is wrong (which it will be, for the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * child to force an exit) and so do an exit anyway.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void ap_start_shutdown(int graceful)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_STOPPING;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (shutdown_pending == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Um, is this _probably_ not an error, if the user has
f4c310fd2555c6faca1f980f00b161eadb089023gstein * tried to do a shutdown twice quickly, so we won't
f4c310fd2555c6faca1f980f00b161eadb089023gstein * worry about reporting it.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
d839a9822ee53ce00da24c15f2d9fe054233d342gstein }
d839a9822ee53ce00da24c15f2d9fe054233d342gstein shutdown_pending = 1;
d839a9822ee53ce00da24c15f2d9fe054233d342gstein is_graceful = graceful;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
d839a9822ee53ce00da24c15f2d9fe054233d342gstein
d839a9822ee53ce00da24c15f2d9fe054233d342gstein/* do a graceful restart if graceful == 1 */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void ap_start_restart(int graceful)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_STOPPING;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (restart_pending == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Probably not an error - don't bother reporting it */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein restart_pending = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein is_graceful = graceful;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void sig_term(int sig)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_start_shutdown(sig == AP_SIG_GRACEFUL_STOP);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void restart(int sig)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_start_restart(sig == AP_SIG_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void set_signals(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef NO_USE_SIGACTION
f4c310fd2555c6faca1f980f00b161eadb089023gstein struct sigaction sa;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!one_process) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_fatal_signal_setup(ap_server_conf, pconf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef NO_USE_SIGACTION
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigemptyset(&sa.sa_mask);
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_flags = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_handler = sig_term;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGTERM, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "sigaction(SIGTERM)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef AP_SIG_GRACEFUL_STOP
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein#ifdef SIGINT
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGINT, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "sigaction(SIGINT)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGXCPU
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_handler = SIG_DFL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGXCPU, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "sigaction(SIGXCPU)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGXFSZ
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_handler = SIG_DFL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGXFSZ, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "sigaction(SIGXFSZ)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGPIPE
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_handler = SIG_IGN;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGPIPE, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "sigaction(SIGPIPE)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy
f4c310fd2555c6faca1f980f00b161eadb089023gstein * processing one */
f4c310fd2555c6faca1f980f00b161eadb089023gstein sigaddset(&sa.sa_mask, SIGHUP);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein sa.sa_handler = restart;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(SIGHUP, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "sigaction(SIGHUP)");
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "sigaction(" AP_SIG_GRACEFUL_STRING ")");
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!one_process) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGXCPU
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(SIGXCPU, SIG_DFL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGXCPU */
50bd75672ef114fb839dd9643c192b432fdf344cgstein#ifdef SIGXFSZ
50bd75672ef114fb839dd9643c192b432fdf344cgstein apr_signal(SIGXFSZ, SIG_DFL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGXFSZ */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein apr_signal(SIGTERM, sig_term);
50bd75672ef114fb839dd9643c192b432fdf344cgstein#ifdef SIGHUP
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(SIGHUP, restart);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGHUP */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef AP_SIG_GRACEFUL
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(AP_SIG_GRACEFUL, restart);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* AP_SIG_GRACEFUL */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef AP_SIG_GRACEFUL_STOP
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(AP_SIG_GRACEFUL_STOP, sig_term);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* AP_SIG_GRACEFUL_STOP */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef SIGPIPE
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(SIGPIPE, SIG_IGN);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* SIGPIPE */
50bd75672ef114fb839dd9643c192b432fdf344cgstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein/*****************************************************************
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Here follows a long bunch of generic server bookkeeping stuff...
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinint ap_graceful_stop_signalled(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX this is really a bad confusing obsolete name
f4c310fd2555c6faca1f980f00b161eadb089023gstein * maybe it should be ap_mpm_process_exiting?
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm */
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* note: for a graceful termination, listener_may_exit will be set before
f4c310fd2555c6faca1f980f00b161eadb089023gstein * workers_may_exit, so check listener_may_exit
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return listener_may_exit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/*****************************************************************
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Child process main loop.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int process_socket(apr_pool_t * p, apr_socket_t * sock,
f4c310fd2555c6faca1f980f00b161eadb089023gstein conn_state_t * cs, int my_child_num,
f4c310fd2555c6faca1f980f00b161eadb089023gstein int my_thread_num)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein conn_rec *c;
f4c310fd2555c6faca1f980f00b161eadb089023gstein listener_poll_type *pt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein long conn_id = ID_FROM_CHILD_THREAD(my_child_num, my_thread_num);
f4c310fd2555c6faca1f980f00b161eadb089023gstein int csd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int rc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_time_t time_now = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_sb_handle_t *sbh;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_create_sb_handle(&sbh, p, my_child_num, my_thread_num);
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein apr_os_sock_get(&csd, sock);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein time_now = apr_time_now();
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (cs == NULL) { /* This is a new connection */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs = apr_pcalloc(p, sizeof(conn_state_t));
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt = apr_pcalloc(p, sizeof(*pt));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->bucket_alloc = apr_bucket_alloc_create(p);
f4c310fd2555c6faca1f980f00b161eadb089023gstein c = ap_run_create_connection(p, ap_server_conf, sock,
f4c310fd2555c6faca1f980f00b161eadb089023gstein conn_id, sbh, cs->bucket_alloc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->c = c;
f4c310fd2555c6faca1f980f00b161eadb089023gstein c->cs = cs;
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->p = p;
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->pfd.desc_type = APR_POLL_SOCKET;
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->pfd.reqevents = APR_POLLIN;
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->pfd.desc.s = sock;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt->type = PT_CSD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt->status = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt->baton = cs;
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein cs->pfd.client_data = pt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_update_vhost_given_ip(c);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = ap_run_pre_connection(c, sock);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != OK && rc != DONE) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
50bd75672ef114fb839dd9643c192b432fdf344cgstein "process_socket: connection aborted");
f4c310fd2555c6faca1f980f00b161eadb089023gstein c->aborted = 1;
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein /**
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * XXX If the platform does not have a usable way of bundling
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein * accept() with a socket readability check, like Win32,
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein * and there are measurable delays before the
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein * socket is readable due to the first data packet arriving,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * it might be better to create the cs on the listener thread,
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein * set the state to CONN_STATE_CHECK_REQUEST_LINE_READABLE,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and give it to the event thread.
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein *
50bd75672ef114fb839dd9643c192b432fdf344cgstein * FreeBSD users will want to enable the HTTP accept filter
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein * module in their kernel for the highest performance
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein * When the accept filter is active, sockets are kept in the
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein * kernel until a HTTP request is received.
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein */
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein cs->state = CONN_STATE_READ_REQUEST_LINE;
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein c = cs->c;
f4c310fd2555c6faca1f980f00b161eadb089023gstein c->sbh = sbh;
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!c->aborted) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_run_process_connection(c);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* state will be updated upon return
f4c310fd2555c6faca1f980f00b161eadb089023gstein * fall thru to either wait for readability/timeout or
f4c310fd2555c6faca1f980f00b161eadb089023gstein * do lingering close
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->state = CONN_STATE_LINGER;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (cs->state == CONN_STATE_LINGER) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_lingering_close(c);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_bucket_alloc_destroy(cs->bucket_alloc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_clear(p);
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein ap_push_pool(worker_queue_info, p);
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (cs->state == CONN_STATE_CHECK_REQUEST_LINE_READABLE) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rc;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm listener_poll_type *pt = (listener_poll_type *) cs->pfd.client_data;
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* It greatly simplifies the logic to use a single timeout value here
f4c310fd2555c6faca1f980f00b161eadb089023gstein * because the new element can just be added to the end of the list and
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * it will stay sorted in expiration time sequence. If brand new
f4c310fd2555c6faca1f980f00b161eadb089023gstein * sockets are sent to the event thread for a readability check, this
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein * will be a slight behavior change - they use the non-keepalive
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein * timeout today. With a normal client, the socket will be readable in
f4c310fd2555c6faca1f980f00b161eadb089023gstein * a few milliseconds anyway.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->expiration_time = ap_server_conf->keep_alive_timeout + time_now;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_mutex_lock(timeout_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_RING_INSERT_TAIL(&timeout_head, cs, conn_state_t, timeout_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt->status = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Add work to pollset. These are always read events */
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = apr_pollset_add(event_pollset, &cs->pfd);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_mutex_unlock(timeout_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "process_socket: apr_pollset_add failure");
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_DEBUG_ASSERT(rc == APR_SUCCESS);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein return 0;
50bd75672ef114fb839dd9643c192b432fdf344cgstein}
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein/* requests_this_child has gone to zero or below. See if the admin coded
50bd75672ef114fb839dd9643c192b432fdf344cgstein "MaxRequestsPerChild 0", and keep going in that case. Doing it this way
50bd75672ef114fb839dd9643c192b432fdf344cgstein simplifies the hot path in worker_thread */
50bd75672ef114fb839dd9643c192b432fdf344cgsteinstatic void check_infinite_requests(void)
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (ap_max_requests_per_child) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein signal_threads(ST_GRACEFUL);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein else {
50bd75672ef114fb839dd9643c192b432fdf344cgstein /* wow! if you're executing this code, you may have set a record.
50bd75672ef114fb839dd9643c192b432fdf344cgstein * either this child process has served over 2 billion requests, or
50bd75672ef114fb839dd9643c192b432fdf344cgstein * you're running a threaded 2.0 on a 16 bit machine.
50bd75672ef114fb839dd9643c192b432fdf344cgstein *
50bd75672ef114fb839dd9643c192b432fdf344cgstein * I'll buy pizza and beers at Apachecon for the first person to do
50bd75672ef114fb839dd9643c192b432fdf344cgstein * the former without cheating (dorking with INT_MAX, or running with
50bd75672ef114fb839dd9643c192b432fdf344cgstein * uncommitted performance patches, for example).
50bd75672ef114fb839dd9643c192b432fdf344cgstein *
50bd75672ef114fb839dd9643c192b432fdf344cgstein * for the latter case, you probably deserve a beer too. Greg Ames
50bd75672ef114fb839dd9643c192b432fdf344cgstein */
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein requests_this_child = INT_MAX; /* keep going */
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein}
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgsteinstatic void unblock_signal(int sig)
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
50bd75672ef114fb839dd9643c192b432fdf344cgstein sigset_t sig_mask;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein sigemptyset(&sig_mask);
50bd75672ef114fb839dd9643c192b432fdf344cgstein sigaddset(&sig_mask, sig);
50bd75672ef114fb839dd9643c192b432fdf344cgstein#if defined(SIGPROCMASK_SETS_THREAD_MASK)
50bd75672ef114fb839dd9643c192b432fdf344cgstein sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
50bd75672ef114fb839dd9643c192b432fdf344cgstein#else
50bd75672ef114fb839dd9643c192b432fdf344cgstein pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL);
50bd75672ef114fb839dd9643c192b432fdf344cgstein#endif
50bd75672ef114fb839dd9643c192b432fdf344cgstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void dummy_signal_handler(int sig)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX If specifying SIG_IGN is guaranteed to unblock a syscall,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * then we don't need this goofy function.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic apr_status_t push2worker(const apr_pollfd_t * pfd,
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pollset_t * pollset)
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein listener_poll_type *pt = (listener_poll_type *) pfd->client_data;
f4c310fd2555c6faca1f980f00b161eadb089023gstein conn_state_t *cs = (conn_state_t *) pt->baton;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pt->status == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt->status = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = apr_pollset_remove(pollset, pfd);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Some of the pollset backends, like KQueue or Epoll
f4c310fd2555c6faca1f980f00b161eadb089023gstein * automagically remove the FD if the socket is closed,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * therefore, we can accept _SUCCESS or _NOTFOUND,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and we still want to keep going
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS && rc != APR_NOTFOUND) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->state = CONN_STATE_LINGER;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = ap_queue_push(worker_queue, cs->pfd.desc.s, cs, cs->p);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* trash the connection; we couldn't queue the connected
f4c310fd2555c6faca1f980f00b161eadb089023gstein * socket to a worker
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_bucket_alloc_destroy(cs->bucket_alloc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_socket_close(cs->pfd.desc.s);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf, "push2worker: ap_queue_push failed");
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_clear(cs->p);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_push_pool(worker_queue_info, cs->p);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return APR_SUCCESS;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* get_worker:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * reserve a worker thread, block if all are currently busy.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * this prevents the worker queue from overflowing and lets
f4c310fd2555c6faca1f980f00b161eadb089023gstein * other processes accept new connections in the mean time.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int get_worker(int *have_idle_worker_p)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!*have_idle_worker_p) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = ap_queue_info_wait_for_idler(worker_queue_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc == APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *have_idle_worker_p = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!APR_STATUS_IS_EOF(rc)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "ap_queue_info_wait_for_idler failed. "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Attempting to shutdown process gracefully");
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal_threads(ST_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* already reserved a worker thread - must have hit a
f4c310fd2555c6faca1f980f00b161eadb089023gstein * transient error on a previous pass
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void *listener_thread(apr_thread_t * thd, void *dummy)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein proc_info *ti = dummy;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int process_slot = ti->pid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_t *tpool = apr_thread_pool_get(thd);
f4c310fd2555c6faca1f980f00b161eadb089023gstein void *csd = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_t *ptrans; /* Pool for per-transaction stuff */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_listen_rec *lr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int have_idle_worker = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein conn_state_t *cs;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const apr_pollfd_t *out_pfd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_int32_t num = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_time_t time_now = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_interval_time_t timeout_interval;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_time_t timeout_time;
f4c310fd2555c6faca1f980f00b161eadb089023gstein listener_poll_type *pt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein free(ti);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We set this to force apr_pollset to wakeup if there hasn't been any IO
f4c310fd2555c6faca1f980f00b161eadb089023gstein * on any of its sockets. This allows sockets to have been added
f4c310fd2555c6faca1f980f00b161eadb089023gstein * when no other keepalive operations where going on.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * current value is 1 second
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein timeout_interval = 1000000;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* the following times out events that are really close in the future
f4c310fd2555c6faca1f980f00b161eadb089023gstein * to prevent extra poll calls
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * current value is .1 second
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define TIMEOUT_FUDGE_FACTOR 100000
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* POLLSET_SCALE_FACTOR * ap_threads_per_child sets the size of
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the pollset. I've seen 15 connections per active worker thread
f4c310fd2555c6faca1f980f00b161eadb089023gstein * running SPECweb99.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * However, with the newer apr_pollset, this is the number of sockets that
f4c310fd2555c6faca1f980f00b161eadb089023gstein * we will return to any *one* call to poll(). Therefore, there is no
f4c310fd2555c6faca1f980f00b161eadb089023gstein * reason to make it more than ap_threads_per_child.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define POLLSET_SCALE_FACTOR 1
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein tpool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "creation of the timeout mutex failed. Attempting to "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "shutdown process gracefully");
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal_threads(ST_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_RING_INIT(&timeout_head, conn_state_t, timeout_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Create the main pollset */
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = apr_pollset_create(&event_pollset,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child * POLLSET_SCALE_FACTOR,
f4c310fd2555c6faca1f980f00b161eadb089023gstein tpool, APR_POLLSET_THREADSAFE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "apr_pollset_create with Thread Safety failed. "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Attempting to shutdown process gracefully");
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal_threads(ST_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (lr = ap_listeners; lr != NULL; lr = lr->next) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pollfd_t pfd = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt = apr_pcalloc(tpool, sizeof(*pt));
f4c310fd2555c6faca1f980f00b161eadb089023gstein pfd.desc_type = APR_POLL_SOCKET;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pfd.desc.s = lr->sd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pfd.reqevents = APR_POLLIN;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt->type = PT_ACCEPT;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt->baton = lr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein pfd.client_data = pt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_socket_opt_set(pfd.desc.s, APR_SO_NONBLOCK, 1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pollset_add(event_pollset, &pfd);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Unblock the signal used to wake this thread up, and set a handler for
f4c310fd2555c6faca1f980f00b161eadb089023gstein * it.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein unblock_signal(LISTENER_SIGNAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(LISTENER_SIGNAL, dummy_signal_handler);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (!listener_may_exit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (requests_this_child <= 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein check_infinite_requests();
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = apr_pollset_poll(event_pollset, timeout_interval, &num,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &out_pfd);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (APR_STATUS_IS_EINTR(rc)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!APR_STATUS_IS_TIMEUP(rc)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "apr_pollset_poll failed. Attempting to "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "shutdown process gracefully");
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal_threads(ST_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (listener_may_exit)
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (num && get_worker(&have_idle_worker)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein pt = (listener_poll_type *) out_pfd->client_data;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pt->type == PT_CSD) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* one of the sockets is readable */
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs = (conn_state_t *) pt->baton;
50bd75672ef114fb839dd9643c192b432fdf344cgstein switch (cs->state) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein case CONN_STATE_CHECK_REQUEST_LINE_READABLE:
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->state = CONN_STATE_READ_REQUEST_LINE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein default:
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, rc,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "event_loop: unexpected state %d",
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->state);
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_DEBUG_ASSERT(0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_mutex_lock(timeout_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_RING_REMOVE(cs, timeout_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_mutex_unlock(timeout_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = push2worker(out_pfd, event_pollset);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf, "push2worker failed");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein have_idle_worker = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* A Listener Socket is ready for an accept() */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_t *recycled_pool = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein lr = (ap_listen_rec *) pt->baton;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_pop_pool(&recycled_pool, worker_queue_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (recycled_pool == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* create a new transaction pool for each accepted socket */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_allocator_t *allocator;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_allocator_create(&allocator);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_allocator_max_free_set(allocator,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_max_mem_free);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_create_ex(&ptrans, pconf, NULL, allocator);
50bd75672ef114fb839dd9643c192b432fdf344cgstein apr_allocator_owner_set(allocator, ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ptrans == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Failed to create transaction pool");
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal_threads(ST_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ptrans = recycled_pool;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_tag(ptrans, "transaction");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = lr->accept_func(&csd, lr, ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* later we trash rv and rely on csd to indicate
f4c310fd2555c6faca1f980f00b161eadb089023gstein * success/failure
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_DEBUG_ASSERT(rc == APR_SUCCESS || !csd);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc == APR_EGENERAL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* E[NM]FILE, ENOMEM, etc */
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_shortage = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal_threads(ST_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (csd != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = ap_queue_push(worker_queue, csd, NULL, ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* trash the connection; we couldn't queue the connected
f4c310fd2555c6faca1f980f00b161eadb089023gstein * socket to a worker
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_socket_close(csd);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rc,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "ap_queue_push failed");
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_clear(ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_push_pool(worker_queue_info, ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein have_idle_worker = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_clear(ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_push_pool(worker_queue_info, ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein } /* if:else on pt->type */
f4c310fd2555c6faca1f980f00b161eadb089023gstein out_pfd++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein num--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein } /* while for processing poll */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX possible optimization: stash the current time for use as
f4c310fd2555c6faca1f980f00b161eadb089023gstein * r->request_time for new requests
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein time_now = apr_time_now();
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* handle timed out sockets */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_mutex_lock(timeout_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs = APR_RING_FIRST(&timeout_head);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm timeout_time = time_now + TIMEOUT_FUDGE_FACTOR;
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (!APR_RING_EMPTY(&timeout_head, conn_state_t, timeout_list)
f4c310fd2555c6faca1f980f00b161eadb089023gstein && cs->expiration_time < timeout_time
f4c310fd2555c6faca1f980f00b161eadb089023gstein && get_worker(&have_idle_worker)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs->state = CONN_STATE_LINGER;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_RING_REMOVE(cs, timeout_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = push2worker(&cs->pfd, event_pollset);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* XXX return NULL looks wrong - not an init failure
f4c310fd2555c6faca1f980f00b161eadb089023gstein * that bypasses all the cleanup outside the main loop
f4c310fd2555c6faca1f980f00b161eadb089023gstein * break seems more like it
f4c310fd2555c6faca1f980f00b161eadb089023gstein * need to evaluate seriousness of push2worker failures
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein have_idle_worker = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein cs = APR_RING_FIRST(&timeout_head);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_mutex_unlock(timeout_mutex);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein } /* listener main loop */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_close_listeners();
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_queue_term(worker_queue);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dying = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->parent[process_slot].quiescing = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* wake up the main thread */
f4c310fd2555c6faca1f980f00b161eadb089023gstein kill(ap_my_pid, SIGTERM);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_exit(thd, APR_SUCCESS);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* XXX For ungraceful termination/restart, we definitely don't want to
f4c310fd2555c6faca1f980f00b161eadb089023gstein * wait for active connections to finish but we may want to wait
f4c310fd2555c6faca1f980f00b161eadb089023gstein * for idle workers to get out of the queue code and release mutexes,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * since those mutexes are cleaned up pretty soon and some systems
f4c310fd2555c6faca1f980f00b161eadb089023gstein * may not react favorably (i.e., segfault) if operations are attempted
f4c310fd2555c6faca1f980f00b161eadb089023gstein * on cleaned-up mutexes.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein proc_info *ti = dummy;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int process_slot = ti->pid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int thread_slot = ti->tid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_socket_t *csd = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein conn_state_t *cs;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_t *ptrans; /* Pool for per-transaction stuff */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int is_idle = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein free(ti);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->servers[process_slot][thread_slot].generation = ap_my_generation;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_update_child_status_from_indexes(process_slot, thread_slot,
f4c310fd2555c6faca1f980f00b161eadb089023gstein SERVER_STARTING, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (!workers_may_exit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!is_idle) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = ap_queue_info_set_idle(worker_queue_info, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "ap_queue_info_set_idle failed. Attempting to "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "shutdown process gracefully.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal_threads(ST_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein is_idle = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_update_child_status_from_indexes(process_slot, thread_slot,
f4c310fd2555c6faca1f980f00b161eadb089023gstein SERVER_READY, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_pop:
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (workers_may_exit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = ap_queue_pop(worker_queue, &csd, &cs, &ptrans);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We get APR_EOF during a graceful shutdown once all the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * connections accepted by this server process have been handled.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (APR_STATUS_IS_EOF(rv)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We get APR_EINTR whenever ap_queue_pop() has been interrupted
f4c310fd2555c6faca1f980f00b161eadb089023gstein * from an explicit call to ap_queue_interrupt_all(). This allows
f4c310fd2555c6faca1f980f00b161eadb089023gstein * us to unblock threads stuck in ap_queue_pop() when a shutdown
f4c310fd2555c6faca1f980f00b161eadb089023gstein * is pending.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * If workers_may_exit is set and this is ungraceful termination/
f4c310fd2555c6faca1f980f00b161eadb089023gstein * restart, we are bound to get an error on some systems (e.g.,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * AIX, which sanity-checks mutex operations) since the queue
f4c310fd2555c6faca1f980f00b161eadb089023gstein * may have already been cleaned up. Don't log the "error" if
f4c310fd2555c6faca1f980f00b161eadb089023gstein * workers_may_exit is set.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (APR_STATUS_IS_EINTR(rv)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein goto worker_pop;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We got some other error. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (!workers_may_exit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "ap_queue_pop failed");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein is_idle = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_sockets[thread_slot] = csd;
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = process_socket(ptrans, csd, cs, process_slot, thread_slot);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!rv) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein requests_this_child--;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_sockets[thread_slot] = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_update_child_status_from_indexes(process_slot, thread_slot,
f4c310fd2555c6faca1f980f00b161eadb089023gstein (dying) ? SERVER_DEAD :
f4c310fd2555c6faca1f980f00b161eadb089023gstein SERVER_GRACEFUL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein (request_rec *) NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_exit(thd, APR_SUCCESS);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic int check_signal(int signum)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm{
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (signum) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein case SIGTERM:
f4c310fd2555c6faca1f980f00b161eadb089023gstein case SIGINT:
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void create_listener_thread(thread_starter * ts)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int my_child_num = ts->child_num_arg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_threadattr_t *thread_attr = ts->threadattr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein proc_info *my_info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info = (proc_info *) malloc(sizeof(proc_info));
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info->pid = my_child_num;
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info->tid = -1; /* listener thread doesn't have a thread slot */
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info->sd = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info, pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "apr_thread_create: unable to create listener thread");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* let the parent decide how bad this really is */
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDSICK);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_os_thread_get(&listener_os_thread, ts->listener);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* XXX under some circumstances not understood, children can get stuck
f4c310fd2555c6faca1f980f00b161eadb089023gstein * in start_threads forever trying to take over slots which will
f4c310fd2555c6faca1f980f00b161eadb089023gstein * never be cleaned up; for now there is an APLOG_DEBUG message issued
f4c310fd2555c6faca1f980f00b161eadb089023gstein * every so often when this condition occurs
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein thread_starter *ts = dummy;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_t **threads = ts->threads;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_threadattr_t *thread_attr = ts->threadattr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int child_num_arg = ts->child_num_arg;
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein int my_child_num = child_num_arg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein proc_info *my_info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int threads_created = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int listener_started = 0;
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein int loops;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int prev_threads_created;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We must create the fd queues before we start up the listener
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and worker threads. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_queue = apr_pcalloc(pchild, sizeof(*worker_queue));
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = ap_queue_init(worker_queue, ap_threads_per_child, pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "ap_queue_init() failed");
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = ap_queue_info_create(&worker_queue_info, pchild,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "ap_queue_info_create() failed");
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_sockets = apr_pcalloc(pchild, ap_threads_per_child
f4c310fd2555c6faca1f980f00b161eadb089023gstein * sizeof(apr_socket_t *));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein loops = prev_threads_created = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ap_threads_per_child does not include the listener thread */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < ap_threads_per_child; i++) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm int status =
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->servers[child_num_arg][i].status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info = (proc_info *) malloc(sizeof(proc_info));
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (my_info == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "malloc: out of memory");
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info->pid = my_child_num;
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info->tid = i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein my_info->sd = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We are creating threads right now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_update_child_status_from_indexes(my_child_num, i,
f4c310fd2555c6faca1f980f00b161eadb089023gstein SERVER_STARTING, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We let each thread update its own scoreboard entry. This is
f4c310fd2555c6faca1f980f00b161eadb089023gstein * done because it lets us deal with tid better.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_thread_create(&threads[i], thread_attr,
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_thread, my_info, pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "apr_thread_create: unable to create worker thread");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* let the parent decide how bad this really is */
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDSICK);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein threads_created++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Start the listener only when there are workers available */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (!listener_started && threads_created) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein create_listener_thread(ts);
f4c310fd2555c6faca1f980f00b161eadb089023gstein listener_started = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (start_thread_may_exit || threads_created == ap_threads_per_child) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* wait for previous generation to clean up an entry */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_sleep(apr_time_from_sec(1));
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++loops;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (loops % 120 == 0) { /* every couple of minutes */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (prev_threads_created == threads_created) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "child %" APR_PID_T_FMT " isn't taking over "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "slots very quickly (%d of %d)",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_my_pid, threads_created,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein prev_threads_created = threads_created;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* What state should this child_main process be listed as in the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * scoreboard...?
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ap_update_child_status_from_indexes(my_child_num, i, SERVER_STARTING,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * (request_rec *) NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * This state should be listed separately in the scoreboard, in some kind
f4c310fd2555c6faca1f980f00b161eadb089023gstein * of process_status, not mixed in with the worker threads' status.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * "life_status" is almost right, but it's in the worker's structure, and
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * the name could be clearer. gla
6b745319b1099edacf401e8911efa480440f999agstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_exit(thd, APR_SUCCESS);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void join_workers(apr_thread_t * listener, apr_thread_t ** threads)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rv, thread_rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (listener) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein int iter;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* deal with a rare timing window which affects waking up the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * listener thread... if the signal sent to the listener thread
f4c310fd2555c6faca1f980f00b161eadb089023gstein * is delivered between the time it verifies that the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * listener_may_exit flag is clear and the time it enters a
f4c310fd2555c6faca1f980f00b161eadb089023gstein * blocking syscall, the signal didn't do any good... work around
f4c310fd2555c6faca1f980f00b161eadb089023gstein * that by sleeping briefly and sending it again
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein iter = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (iter < 10 &&
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAVE_PTHREAD_KILL
f4c310fd2555c6faca1f980f00b161eadb089023gstein pthread_kill(*listener_os_thread, 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein#else
6b745319b1099edacf401e8911efa480440f999agstein kill(ap_my_pid, 0)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#endif
6b745319b1099edacf401e8911efa480440f999agstein == 0) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* listener not dead yet */
6b745319b1099edacf401e8911efa480440f999agstein apr_sleep(apr_time_make(0, 500000));
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm wakeup_listener();
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++iter;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (iter >= 10) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "the listener thread didn't exit");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_thread_join(&thread_rv, listener);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "apr_thread_join: unable to join listener thread");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < ap_threads_per_child; i++) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (threads[i]) { /* if we ever created this thread */
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_thread_join(&thread_rv, threads[i]);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm "apr_thread_join: unable to join worker "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "thread %d", i);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void join_start_thread(apr_thread_t * start_thread_id)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_status_t rv, thread_rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein start_thread_may_exit = 1; /* tell it to give up in case it is still
f4c310fd2555c6faca1f980f00b161eadb089023gstein * trying to take over slots from a
f4c310fd2555c6faca1f980f00b161eadb089023gstein * previous generation
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_thread_join(&thread_rv, start_thread_id);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "apr_thread_join: unable to join the start " "thread");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void child_main(int child_num_arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_t **threads;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein thread_starter *ts;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_threadattr_t *thread_attr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_thread_t *start_thread_id;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * child initializes
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_my_pid = getpid();
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_fatal_signal_child_setup(ap_server_conf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_create(&pchild, pconf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*stuff to do before we switch id's, so we have permissions. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_reopen_scoreboard(pchild, NULL, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (unixd_setup_child()) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_run_child_init(pchild, ap_server_conf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* done with init critical section */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Just use the standard apr_setup_signal_thread to block all signals
f4c310fd2555c6faca1f980f00b161eadb089023gstein * from being received. The child processes no longer use signals for
f4c310fd2555c6faca1f980f00b161eadb089023gstein * any communication with the parent process.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_setup_signal_thread();
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Couldn't initialize signal thread");
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_max_requests_per_child) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm requests_this_child = ap_max_requests_per_child;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* coding a value of zero means infinity */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm requests_this_child = INT_MAX;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Setup worker threads */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* clear the storage; we may not create all our threads immediately,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and we want a 0 entry to indicate a thread which was not created
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein threads = (apr_thread_t **) calloc(1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein sizeof(apr_thread_t *) *
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (threads == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, errno, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "malloc: out of memory");
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDFATAL);
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein }
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ts = (thread_starter *) apr_palloc(pchild, sizeof(*ts));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_threadattr_create(&thread_attr, pchild);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* 0 means PTHREAD_CREATE_JOINABLE */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_threadattr_detach_set(thread_attr, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if (ap_thread_stacksize != 0) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein apr_threadattr_stacksize_set(thread_attr, ap_thread_stacksize);
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ts->threads = threads;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ts->listener = NULL;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ts->child_num_arg = child_num_arg;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ts->threadattr = thread_attr;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein rv = apr_thread_create(&start_thread_id, thread_attr, start_threads,
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ts, pchild);
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if (rv != APR_SUCCESS) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "apr_thread_create: unable to create worker thread");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* let the parent decide how bad this really is */
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(APEXIT_CHILDSICK);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_RUNNING;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If we are only running in one_process mode, we will want to
f4c310fd2555c6faca1f980f00b161eadb089023gstein * still handle signals. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (one_process) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Block until we get a terminating signal. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal_thread(check_signal);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure the start thread has finished; signal_threads()
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and join_workers() depend on that
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX join_start_thread() won't be awakened if one of our
f4c310fd2555c6faca1f980f00b161eadb089023gstein * threads encounters a critical error and attempts to
f4c310fd2555c6faca1f980f00b161eadb089023gstein * shutdown this child
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein join_start_thread(start_thread_id);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* helps us terminate a little more quickly than the dispatch of the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * signal thread; beats the Pipe of Death and the browsers
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein signal_threads(ST_UNGRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* A terminating signal was received. Now join each of the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * workers to clean them up.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * If the worker already exited, then the join frees
f4c310fd2555c6faca1f980f00b161eadb089023gstein * their resources and returns.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * If the worker hasn't exited, then this blocks until
f4c310fd2555c6faca1f980f00b161eadb089023gstein * they have (then cleans up).
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein join_workers(ts->listener, threads);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else { /* !one_process */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* remove SIGTERM from the set of blocked signals... if one of
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the other threads in the process needs to take us down
f4c310fd2555c6faca1f980f00b161eadb089023gstein * (e.g., for MaxRequestsPerChild) it will send us SIGTERM
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein unblock_signal(SIGTERM);
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(SIGTERM, dummy_signal_handler);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Watch for any messages from the parent over the POD */
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = ap_mpm_pod_check(pod);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv == AP_NORESTART) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* see if termination was triggered while we slept */
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (terminate_mode) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein case ST_GRACEFUL:
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = AP_GRACEFUL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein case ST_UNGRACEFUL:
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = AP_RESTART;
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv == AP_GRACEFUL || rv == AP_RESTART) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure the start thread has finished;
f4c310fd2555c6faca1f980f00b161eadb089023gstein * signal_threads() and join_workers depend on that
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein join_start_thread(start_thread_id);
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein signal_threads(rv ==
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein AP_GRACEFUL ? ST_GRACEFUL : ST_UNGRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* A terminating signal was received. Now join each of the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * workers to clean them up.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * If the worker already exited, then the join frees
f4c310fd2555c6faca1f980f00b161eadb089023gstein * their resources and returns.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * If the worker hasn't exited, then this blocks until
f4c310fd2555c6faca1f980f00b161eadb089023gstein * they have (then cleans up).
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein join_workers(ts->listener, threads);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein free(threads);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(resource_shortage ? APEXIT_CHILDSICK : 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int make_child(server_rec * s, int slot)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int pid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (slot + 1 > ap_max_daemons_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_max_daemons_limit = slot + 1;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (one_process) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein set_signals();
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->parent[slot].pid = getpid();
f4c310fd2555c6faca1f980f00b161eadb089023gstein child_main(slot);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((pid = fork()) == -1) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_log_error(APLOG_MARK, APLOG_ERR, errno, s,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "fork: Unable to fork new process");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* fork didn't succeed. Fix the scoreboard or else
f4c310fd2555c6faca1f980f00b161eadb089023gstein * it will say SERVER_STARTING forever and ever
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, NULL);
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* In case system resources are maxxed out, we don't want
f4c310fd2555c6faca1f980f00b161eadb089023gstein Apache running away with the CPU trying to fork over and
f4c310fd2555c6faca1f980f00b161eadb089023gstein over and over again. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_sleep(apr_time_from_sec(10));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!pid) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef HAVE_BINDPROCESSOR
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* By default, AIX binds to a single processor. This bit unbinds
f4c310fd2555c6faca1f980f00b161eadb089023gstein * children which will then bind to another CPU.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein int status = bindprocessor(BINDPROCESS, (int) getpid(),
f4c310fd2555c6faca1f980f00b161eadb089023gstein PROCESSOR_CLASS_ANY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (status != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, errno,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "processor unbind failed %d", status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein RAISE_SIGSTOP(MAKE_CHILD);
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(SIGTERM, just_die);
f4c310fd2555c6faca1f980f00b161eadb089023gstein child_main(slot);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein clean_child_exit(0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* else */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->parent[slot].quiescing = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->parent[slot].pid = pid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* start up a bunch of children */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void startup_children(int number_to_start)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_scoreboard_image->parent[i].pid != 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (make_child(ap_server_conf, i) < 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein --number_to_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * idle_spawn_rate is the number of children that will be spawned on the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * next maintenance cycle if there aren't enough idle servers. It is
f4c310fd2555c6faca1f980f00b161eadb089023gstein * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
f4c310fd2555c6faca1f980f00b161eadb089023gstein * without the need to spawn.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int idle_spawn_rate = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifndef MAX_SPAWN_RATE
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define MAX_SPAWN_RATE (32)
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int hold_off_on_exponential_spawning;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void perform_idle_server_maintenance(void)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i, j;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int idle_thread_count;
f4c310fd2555c6faca1f980f00b161eadb089023gstein worker_score *ws;
f4c310fd2555c6faca1f980f00b161eadb089023gstein process_score *ps;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int free_length;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int totally_free_length = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int free_slots[MAX_SPAWN_RATE];
f4c310fd2555c6faca1f980f00b161eadb089023gstein int last_non_dead;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int total_non_dead;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int active_thread_count = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* initialize the free_list */
f4c310fd2555c6faca1f980f00b161eadb089023gstein free_length = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein idle_thread_count = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein last_non_dead = -1;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm total_non_dead = 0;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < ap_daemons_limit; ++i) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein /* Initialization to satisfy the compiler. It doesn't know
f4c310fd2555c6faca1f980f00b161eadb089023gstein * that ap_threads_per_child is always > 0 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein int status = SERVER_DEAD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int any_dying_threads = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int any_dead_threads = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int all_dead_threads = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (i >= ap_max_daemons_limit
f4c310fd2555c6faca1f980f00b161eadb089023gstein && totally_free_length == idle_spawn_rate)
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ps = &ap_scoreboard_image->parent[i];
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein for (j = 0; j < ap_threads_per_child; j++) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ws = &ap_scoreboard_image->servers[i][j];
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein status = ws->status;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX any_dying_threads is probably no longer needed GLA */
f4c310fd2555c6faca1f980f00b161eadb089023gstein any_dying_threads = any_dying_threads ||
f4c310fd2555c6faca1f980f00b161eadb089023gstein (status == SERVER_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein any_dead_threads = any_dead_threads || (status == SERVER_DEAD);
f4c310fd2555c6faca1f980f00b161eadb089023gstein all_dead_threads = all_dead_threads &&
f4c310fd2555c6faca1f980f00b161eadb089023gstein (status == SERVER_DEAD || status == SERVER_GRACEFUL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We consider a starting server as idle because we started it
f4c310fd2555c6faca1f980f00b161eadb089023gstein * at least a cycle ago, and if it still hasn't finished starting
f4c310fd2555c6faca1f980f00b161eadb089023gstein * then we're just going to swamp things worse by forking more.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * So we hopefully won't need to fork more if we count it.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * This depends on the ordering of SERVER_READY and SERVER_STARTING.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ps->pid != 0) { /* XXX just set all_dead_threads in outer
f4c310fd2555c6faca1f980f00b161eadb089023gstein for loop if no pid? not much else matters */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (status <= SERVER_READY && status != SERVER_DEAD &&
f4c310fd2555c6faca1f980f00b161eadb089023gstein !ps->quiescing && ps->generation == ap_my_generation) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++idle_thread_count;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++active_thread_count;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (any_dead_threads
f4c310fd2555c6faca1f980f00b161eadb089023gstein && totally_free_length < idle_spawn_rate
f4c310fd2555c6faca1f980f00b161eadb089023gstein && free_length < MAX_SPAWN_RATE
f4c310fd2555c6faca1f980f00b161eadb089023gstein && (!ps->pid /* no process in the slot */
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein || ps->quiescing)) { /* or at least one is going away */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (all_dead_threads) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* great! we prefer these, because the new process can
f4c310fd2555c6faca1f980f00b161eadb089023gstein * start more threads sooner. So prioritize this slot
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein * by putting it ahead of any slots with active threads.
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein *
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein * first, make room by moving a slot that's potentially still
f4c310fd2555c6faca1f980f00b161eadb089023gstein * in use to the end of the array
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein free_slots[free_length] = free_slots[totally_free_length];
f4c310fd2555c6faca1f980f00b161eadb089023gstein free_slots[totally_free_length++] = i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* slot is still in use - back of the bus
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm free_slots[free_length] = i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ++free_length;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX if (!ps->quiescing) is probably more reliable GLA */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!any_dying_threads) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein last_non_dead = i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++total_non_dead;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if (sick_child_detected) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if (active_thread_count > 0) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein /* some child processes appear to be working. don't kill the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * whole server.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein sick_child_detected = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein /* looks like a basket case. give up.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein shutdown_pending = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein child_fatal = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "No active workers found..."
f4c310fd2555c6faca1f980f00b161eadb089023gstein " Apache is exiting!");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the child already logged the failure details */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_max_daemons_limit = last_non_dead + 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (idle_thread_count > max_spare_threads) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Kill off one child */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_pod_signal(pod, TRUE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein idle_spawn_rate = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (idle_thread_count < min_spare_threads) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* terminate the free list */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (free_length == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* only report this condition once */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm static int reported = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!reported) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "server reached MaxClients setting, consider"
f4c310fd2555c6faca1f980f00b161eadb089023gstein " raising the MaxClients setting");
f4c310fd2555c6faca1f980f00b161eadb089023gstein reported = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein idle_spawn_rate = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (free_length > idle_spawn_rate) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein free_length = idle_spawn_rate;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (idle_spawn_rate >= 8) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_INFO, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "server seems busy, (you may need "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "to increase StartServers, ThreadsPerChild "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "or Min/MaxSpareThreads), "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "spawning %d children, there are around %d idle "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "threads, and %d total children", free_length,
f4c310fd2555c6faca1f980f00b161eadb089023gstein idle_thread_count, total_non_dead);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < free_length; ++i) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein make_child(ap_server_conf, free_slots[i]);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the next time around we want to spawn twice as many if this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * wasn't good enough, but not if we've just done a graceful
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if (hold_off_on_exponential_spawning) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein --hold_off_on_exponential_spawning;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (idle_spawn_rate < MAX_SPAWN_RATE) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein idle_spawn_rate *= 2;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein idle_spawn_rate = 1;
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void server_main_loop(int remaining_children_to_start)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int child_slot;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_exit_why_e exitwhy;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int status, processed_status;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein apr_proc_t pid;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (!restart_pending && !shutdown_pending) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_wait_or_timeout(&exitwhy, &status, &pid, pconf);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pid.pid != -1) {
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein processed_status = ap_process_child_status(&pid, exitwhy, status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (processed_status == APEXIT_CHILDFATAL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein shutdown_pending = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein child_fatal = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (processed_status == APEXIT_CHILDSICK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* tell perform_idle_server_maintenance to check into this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * on the next timer pop
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein sick_child_detected = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* non-fatal death... note that it's gone in the scoreboard. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein child_slot = find_child_by_pid(&pid);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (child_slot >= 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = 0; i < ap_threads_per_child; i++)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_update_child_status_from_indexes(child_slot, i,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm SERVER_DEAD,
f4c310fd2555c6faca1f980f00b161eadb089023gstein (request_rec *) NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->parent[child_slot].pid = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->parent[child_slot].quiescing = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (processed_status == APEXIT_CHILDSICK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* resource shortage, minimize the fork rate */
f4c310fd2555c6faca1f980f00b161eadb089023gstein idle_spawn_rate = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (remaining_children_to_start
f4c310fd2555c6faca1f980f00b161eadb089023gstein && child_slot < ap_daemons_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we're still doing a 1-for-1 replacement of dead
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * children with new children
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein make_child(ap_server_conf, child_slot);
f4c310fd2555c6faca1f980f00b161eadb089023gstein --remaining_children_to_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein#if APR_HAS_OTHER_CHILD
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (apr_proc_other_child_alert(&pid, APR_OC_REASON_DEATH,
f4c310fd2555c6faca1f980f00b161eadb089023gstein status) == 0) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein /* handled */
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (is_graceful) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Great, we've probably just lost a slot in the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * scoreboard. Somehow we don't know about this child.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "long lost child came home! (pid %ld)",
f4c310fd2555c6faca1f980f00b161eadb089023gstein (long) pid.pid);
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Don't perform idle maintenance when a child dies,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * only do it when there's a timeout. Remember only a
f4c310fd2555c6faca1f980f00b161eadb089023gstein * finite number of children can die, and it's pretty
f4c310fd2555c6faca1f980f00b161eadb089023gstein * pathological for a lot to die suddenly.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (remaining_children_to_start) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* we hit a 1 second timeout in which none of the previous
f4c310fd2555c6faca1f980f00b161eadb089023gstein * generation of children needed to be reaped... so assume
f4c310fd2555c6faca1f980f00b161eadb089023gstein * they're all done, and pick up the slack if any is left.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein startup_children(remaining_children_to_start);
f4c310fd2555c6faca1f980f00b161eadb089023gstein remaining_children_to_start = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* In any event we really shouldn't do the code below because
f4c310fd2555c6faca1f980f00b161eadb089023gstein * few of the servers we just started are in the IDLE state
f4c310fd2555c6faca1f980f00b161eadb089023gstein * yet, so we'd mistakenly create an extra server.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein perform_idle_server_maintenance();
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinint ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int remaining_children_to_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_pid(pconf, ap_pid_fname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein first_server_limit = server_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein first_thread_limit = thread_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (changed_limit_at_restart) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: Attempt to change ServerLimit or ThreadLimit "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "ignored during restart");
f4c310fd2555c6faca1f980f00b161eadb089023gstein changed_limit_at_restart = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!is_graceful) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_STOPPING;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* fix the generation number in the global score; we just got a new,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * cleared scoreboard
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->global->running_generation = ap_my_generation;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein set_signals();
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Don't thrash... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (max_spare_threads < min_spare_threads + ap_threads_per_child)
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_spare_threads = min_spare_threads + ap_threads_per_child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If we're doing a graceful_restart then we're going to see a lot
f4c310fd2555c6faca1f980f00b161eadb089023gstein * of children exiting immediately when we get into the main loop
f4c310fd2555c6faca1f980f00b161eadb089023gstein * below (because we just sent them AP_SIG_GRACEFUL). This happens pretty
f4c310fd2555c6faca1f980f00b161eadb089023gstein * rapidly... and for each one that exits we'll start a new one until
f4c310fd2555c6faca1f980f00b161eadb089023gstein * we reach at least daemons_min_free. But we may be permitted to
f4c310fd2555c6faca1f980f00b161eadb089023gstein * start more than that, so we'll just keep track of how many we're
f4c310fd2555c6faca1f980f00b161eadb089023gstein * supposed to start up without the 1 second penalty between each fork.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm remaining_children_to_start = ap_daemons_to_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (remaining_children_to_start > ap_daemons_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein remaining_children_to_start = ap_daemons_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!is_graceful) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein startup_children(remaining_children_to_start);
f4c310fd2555c6faca1f980f00b161eadb089023gstein remaining_children_to_start = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* give the system some time to recover before kicking into
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein * exponential mode */
f4c310fd2555c6faca1f980f00b161eadb089023gstein hold_off_on_exponential_spawning = 10;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "%s configured -- resuming normal operations",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_get_server_version());
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Server built: %s", ap_get_server_built());
f4c310fd2555c6faca1f980f00b161eadb089023gstein
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe restart_pending = shutdown_pending = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_RUNNING;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein server_main_loop(remaining_children_to_start);
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_STOPPING;
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (shutdown_pending && !is_graceful) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Time to shut down:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Kill child processes, tell them to call child_exit, etc...
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_reclaim_child_processes(1); /* Start with SIGTERM */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!child_fatal) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* cleanup pid file on normal shutdown */
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *pidfile = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pidfile = ap_server_root_relative(pconf, ap_pid_fname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pidfile != NULL && unlink(pidfile) == 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_INFO, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "removed PID file %s (pid=%ld)",
f4c310fd2555c6faca1f980f00b161eadb089023gstein pidfile, (long) getpid());
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf, "caught SIGTERM, shutting down");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein } else if (shutdown_pending) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Time to gracefully shut down:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Kill child processes, tell them to call child_exit, etc...
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein int active_children;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int index;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_time_t cutoff = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Close our listeners, and then ask our children to do same */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_close_listeners();
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_relieve_child_processes();
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!child_fatal) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* cleanup pid file on normal shutdown */
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *pidfile = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pidfile = ap_server_root_relative (pconf, ap_pid_fname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ( pidfile != NULL && unlink(pidfile) == 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_INFO, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "removed PID file %s (pid=%ld)",
f4c310fd2555c6faca1f980f00b161eadb089023gstein pidfile, (long)getpid());
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOTICE, 0,
50bd75672ef114fb839dd9643c192b432fdf344cgstein ap_server_conf, "caught SIGTERM, shutting down");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Don't really exit until each child has finished */
f4c310fd2555c6faca1f980f00b161eadb089023gstein shutdown_pending = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein do {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Pause for a second */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_sleep(apr_time_from_sec(1));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Relieve any children which have now exited */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_relieve_child_processes();
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein active_children = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (index = 0; index < ap_daemons_limit; ++index) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (MPM_CHILD_PID(index) != 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (kill(MPM_CHILD_PID(index), 0) == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein active_children = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Having just one child is enough to stay around */
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein } while (!shutdown_pending && active_children &&
f4c310fd2555c6faca1f980f00b161eadb089023gstein (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We might be here because we received SIGTERM, either
f4c310fd2555c6faca1f980f00b161eadb089023gstein * way, try and make sure that all of our processes are
f4c310fd2555c6faca1f980f00b161eadb089023gstein * really dead.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_reclaim_child_processes(1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we've been told to restart */
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_signal(SIGHUP, SIG_IGN);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (one_process) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* not worth thinking about */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* advance to the next generation */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX: we really need to make sure this new generation number isn't in
f4c310fd2555c6faca1f980f00b161eadb089023gstein * use by any of the children.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++ap_my_generation;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_scoreboard_image->global->running_generation = ap_my_generation;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_graceful) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_SIG_GRACEFUL_STRING
f4c310fd2555c6faca1f980f00b161eadb089023gstein " received. Doing graceful restart");
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* wake up the children...time to die. But we'll have more soon */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_pod_killpg(pod, ap_daemons_limit, TRUE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This is mostly for debugging... so that we know what is still
f4c310fd2555c6faca1f980f00b161eadb089023gstein * gracefully dealing with existing request.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Kill 'em all. Since the child acts the same on the parents SIGTERM
f4c310fd2555c6faca1f980f00b161eadb089023gstein * and a SIGHUP, we may as well use the same signal, because some user
f4c310fd2555c6faca1f980f00b161eadb089023gstein * pthreads are stealing signals from us left and right.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_pod_killpg(pod, ap_daemons_limit, FALSE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_reclaim_child_processes(1); /* Start with SIGTERM */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "SIGHUP received. Attempting to restart");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* This really should be a post_config hook, but the error log is already
f4c310fd2555c6faca1f980f00b161eadb089023gstein * redirected by that point, so we need to do this in the open_logs phase.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int worker_open_logs(apr_pool_t * p, apr_pool_t * plog,
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_t * ptemp, server_rec * s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein pconf = p;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_server_conf = s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ALERT | APLOG_STARTUP, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, "no listening sockets available, shutting down");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!one_process) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein if ((rv = ap_mpm_pod_open(pconf, &pod))) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT | APLOG_STARTUP, rv, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not open pipe-of-death.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return OK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int worker_pre_config(apr_pool_t * pconf, apr_pool_t * plog,
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pool_t * ptemp)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein static int restart_num = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int no_detach, debug, foreground;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_directive_t *pdir;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_directive_t *max_clients = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_status_t rv;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein mpm_state = AP_MPMQ_STARTING;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure that "ThreadsPerChild" gets set before "MaxClients" */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (strncasecmp(pdir->directive, "ThreadsPerChild", 15) == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!max_clients) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we're in the clear, got ThreadsPerChild first */
4b28d4385b48010bc271cba9b40b56e458cbd5d8keith break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
50bd75672ef114fb839dd9643c192b432fdf344cgstein /* now to swap the data */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_directive_t temp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein temp.directive = pdir->directive;
f4c310fd2555c6faca1f980f00b161eadb089023gstein temp.args = pdir->args;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Make sure you don't change 'next', or you may get loops! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX: first_child, parent, and data can never be set
f4c310fd2555c6faca1f980f00b161eadb089023gstein * for these directives, right? -aaron */
f4c310fd2555c6faca1f980f00b161eadb089023gstein temp.filename = pdir->filename;
f4c310fd2555c6faca1f980f00b161eadb089023gstein temp.line_num = pdir->line_num;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein pdir->directive = max_clients->directive;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pdir->args = max_clients->args;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pdir->filename = max_clients->filename;
f4c310fd2555c6faca1f980f00b161eadb089023gstein pdir->line_num = max_clients->line_num;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients->directive = temp.directive;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm max_clients->args = temp.args;
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients->filename = temp.filename;
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients->line_num = temp.line_num;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm break;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (!max_clients
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm && strncasecmp(pdir->directive, "MaxClients", 10) == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients = pdir;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein debug = ap_exists_config_define("DEBUG");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (debug) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein foreground = one_process = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein no_detach = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein one_process = ap_exists_config_define("ONE_PROCESS");
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein no_detach = ap_exists_config_define("NO_DETACH");
f4c310fd2555c6faca1f980f00b161eadb089023gstein foreground = ap_exists_config_define("FOREGROUND");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* sigh, want this only the second time around */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (restart_num++ == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein is_graceful = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_pollset_create(&event_pollset, 1, plog,
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_POLLSET_THREADSAFE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Couldn't create a Thread Safe Pollset. "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Is it supported on your platform?");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_INTERNAL_SERVER_ERROR;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_pollset_destroy(event_pollset);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!one_process && !foreground) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND
f4c310fd2555c6faca1f980f00b161eadb089023gstein : APR_PROC_DETACH_DAEMONIZE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rv != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "apr_proc_detach failed");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_INTERNAL_SERVER_ERROR;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein parent_pid = ap_my_pid = getpid();
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein unixd_pre_config(ptemp);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_listen_pre_config();
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_to_start = DEFAULT_START_DAEMON;
f4c310fd2555c6faca1f980f00b161eadb089023gstein min_spare_threads = DEFAULT_MIN_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_spare_threads = DEFAULT_MAX_FREE_DAEMON * DEFAULT_THREADS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit = server_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_pid_fname = DEFAULT_PIDLOG;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_lock_fname = DEFAULT_LOCKFILE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_extended_status = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return OK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void event_hooks(apr_pool_t * p)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The worker open_logs phase must run before the core's, or stderr
f4c310fd2555c6faca1f980f00b161eadb089023gstein * will be redirected to a file, and the messages won't print to the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * console.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein static const char *const aszSucc[] = { "core.c", NULL };
f4c310fd2555c6faca1f980f00b161eadb089023gstein one_process = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_hook_open_logs(worker_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we need to set the MPM state before other pre-config hooks use MPM query
f4c310fd2555c6faca1f980f00b161eadb089023gstein * to retrieve it, so register as REALLY_FIRST
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_hook_pre_config(worker_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_daemons_to_start(cmd_parms *cmd, void *dummy,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_to_start = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_min_spare_threads(cmd_parms * cmd, void *dummy,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein min_spare_threads = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (min_spare_threads <= 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: detected MinSpareThreads set to non-positive.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Resetting to 1 to avoid almost certain Apache failure.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Please read the documentation.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein min_spare_threads = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_max_spare_threads(cmd_parms * cmd, void *dummy,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_spare_threads = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_max_clients(cmd_parms * cmd, void *dummy,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int max_clients;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* It is ok to use ap_threads_per_child here because we are
f4c310fd2555c6faca1f980f00b161eadb089023gstein * sure that it gets set before MaxClients in the pre_config stage. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (max_clients < ap_threads_per_child) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: MaxClients (%d) must be at least as large",
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " as ThreadsPerChild (%d). Automatically",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " increasing MaxClients to %d.", ap_threads_per_child);
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients = ap_threads_per_child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit = max_clients / ap_threads_per_child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((max_clients > 0) && (max_clients % ap_threads_per_child)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: MaxClients (%d) is not an integer multiple",
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " of ThreadsPerChild (%d), lowering MaxClients to %d",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit * ap_threads_per_child);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " for a maximum of %d child processes,",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit);
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients = ap_daemons_limit * ap_threads_per_child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_daemons_limit > server_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: MaxClients of %d would require %d servers,",
f4c310fd2555c6faca1f980f00b161eadb089023gstein max_clients, ap_daemons_limit);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " and would exceed the ServerLimit value of %d.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein server_limit);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " Automatically lowering MaxClients to %d. To increase,",
f4c310fd2555c6faca1f980f00b161eadb089023gstein server_limit * ap_threads_per_child);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " please see the ServerLimit directive.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit = server_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (ap_daemons_limit < 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: Require MaxClients > 0, setting to 1");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_daemons_limit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_threads_per_child(cmd_parms * cmd, void *dummy,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_threads_per_child > thread_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: ThreadsPerChild of %d exceeds ThreadLimit "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "value of %d", ap_threads_per_child, thread_limit);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "threads, lowering ThreadsPerChild to %d. To increase, "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "please see the", thread_limit);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " ThreadLimit directive.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child = thread_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (ap_threads_per_child < 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: Require ThreadsPerChild > 0, setting to 1");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_threads_per_child = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int tmp_server_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein tmp_server_limit = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* you cannot change ServerLimit across a restart; ignore
f4c310fd2555c6faca1f980f00b161eadb089023gstein * any such attempts
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (first_server_limit &&
f4c310fd2555c6faca1f980f00b161eadb089023gstein tmp_server_limit != server_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* how do we log a message? the error log is a bit bucket at this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * point; we'll just have to set a flag so that ap_mpm_run()
f4c310fd2555c6faca1f980f00b161eadb089023gstein * logs a warning later
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein changed_limit_at_restart = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein server_limit = tmp_server_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (server_limit > MAX_SERVER_LIMIT) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: ServerLimit of %d exceeds compile time limit "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "of %d servers,", server_limit, MAX_SERVER_LIMIT);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein " lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
f4c310fd2555c6faca1f980f00b161eadb089023gstein server_limit = MAX_SERVER_LIMIT;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (server_limit < 1) {
4b28d4385b48010bc271cba9b40b56e458cbd5d8keith ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
4b28d4385b48010bc271cba9b40b56e458cbd5d8keith "WARNING: Require ServerLimit > 0, setting to 1");
f4c310fd2555c6faca1f980f00b161eadb089023gstein server_limit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *set_thread_limit(cmd_parms * cmd, void *dummy,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int tmp_thread_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein tmp_thread_limit = atoi(arg);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* you cannot change ThreadLimit across a restart; ignore
f4c310fd2555c6faca1f980f00b161eadb089023gstein * any such attempts
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (first_thread_limit && tmp_thread_limit != thread_limit) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* how do we log a message? the error log is a bit bucket at this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * point; we'll just have to set a flag so that ap_mpm_run()
f4c310fd2555c6faca1f980f00b161eadb089023gstein * logs a warning later
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein changed_limit_at_restart = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein thread_limit = tmp_thread_limit;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (thread_limit > MAX_THREAD_LIMIT) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: ThreadLimit of %d exceeds compile time limit "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "of %d servers,", thread_limit, MAX_THREAD_LIMIT);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm " lowering ThreadLimit to %d.", MAX_THREAD_LIMIT);
f4c310fd2555c6faca1f980f00b161eadb089023gstein thread_limit = MAX_THREAD_LIMIT;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (thread_limit < 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "WARNING: Require ThreadLimit > 0, setting to 1");
f4c310fd2555c6faca1f980f00b161eadb089023gstein thread_limit = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const command_rec event_cmds[] = {
f4c310fd2555c6faca1f980f00b161eadb089023gstein UNIX_DAEMON_COMMANDS,
f4c310fd2555c6faca1f980f00b161eadb089023gstein LISTEN_COMMANDS,
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_TAKE1("StartServers", set_daemons_to_start, NULL, RSRC_CONF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Number of child processes launched at server startup"),
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of child processes for this run of Apache"),
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_TAKE1("MinSpareThreads", set_min_spare_threads, NULL, RSRC_CONF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Minimum number of idle threads, to handle request spikes"),
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_TAKE1("MaxSpareThreads", set_max_spare_threads, NULL, RSRC_CONF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of idle threads"),
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of threads alive at the same time"),
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_TAKE1("ThreadsPerChild", set_threads_per_child, NULL, RSRC_CONF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Number of threads each child creates"),
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Maximum number of worker threads per child process for this "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "run of Apache - Upper limit for ThreadsPerChild"),
f4c310fd2555c6faca1f980f00b161eadb089023gstein AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND,
f4c310fd2555c6faca1f980f00b161eadb089023gstein {NULL}
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinmodule AP_MODULE_DECLARE_DATA mpm_event_module = {
f4c310fd2555c6faca1f980f00b161eadb089023gstein MPM20_MODULE_STUFF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_mpm_rewrite_args, /* hook to run before apache parses args */
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* create per-directory config structure */
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* merge per-directory config structures */
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* create per-server config structure */
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL, /* merge per-server config structures */
f4c310fd2555c6faca1f980f00b161eadb089023gstein event_cmds, /* command apr_table_t */
f4c310fd2555c6faca1f980f00b161eadb089023gstein event_hooks /* register_hooks */
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein