From owner-svn-ports-head@FreeBSD.ORG Sat Mar 2 19:31:50 2013 Return-Path: Delivered-To: svn-ports-head@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id B0BF8273; Sat, 2 Mar 2013 19:31:50 +0000 (UTC) (envelope-from ohauer@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 873F9EE2; Sat, 2 Mar 2013 19:31:50 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r22JVoXZ014057; Sat, 2 Mar 2013 19:31:50 GMT (envelope-from ohauer@svn.freebsd.org) Received: (from ohauer@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r22JVoVA014051; Sat, 2 Mar 2013 19:31:50 GMT (envelope-from ohauer@svn.freebsd.org) Message-Id: <201303021931.r22JVoVA014051@svn.freebsd.org> From: Olli Hauer Date: Sat, 2 Mar 2013 19:31:50 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r313287 - in head/www: apache22 apache22-itk-mpm apache22-itk-mpm/files apache22/files X-SVN-Group: ports-head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the ports tree for head List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 Mar 2013 19:31:50 -0000 Author: ohauer Date: Sat Mar 2 19:31:49 2013 New Revision: 313287 URL: http://svnweb.freebsd.org/changeset/ports/313287 Log: - update to version 2.2.24 - move mpm itk patches to itk-mpm/files dir - add sshd to REQUIRE line in the rc script to prevent boot issues in case a SSL cert is password protected [1] Changes with Apache 2.2.24 SECURITY: CVE-2012-3499 (cve.mitre.org) Various XSS flaws due to unescaped hostnames and URIs HTML output in mod_info, mod_status, mod_imagemap, mod_ldap, and mod_proxy_ftp. [Jim Jagielski, Stefan Fritsch, Niels Heinen ] SECURITY: CVE-2012-4558 (cve.mitre.org) XSS in mod_proxy_balancer manager interface. [Jim Jagielski, Niels Heinen ] mod_rewrite: Stop merging RewriteBase down to subdirectories unless new option 'RewriteOptions MergeBase' is configured. Merging RewriteBase was unconditionally turned on in 2.2.23. PR 53963. [Eric Covener] mod_ssl: Send the error message for speaking http to an https port using HTTP/1.0 instead of HTTP/0.9, and omit the link that may be wrong when using SNI. PR 50823. [Stefan Fritsch] mod_ssl: log revoked certificates at level INFO instead of DEBUG. PR 52162. [Stefan Fritsch] mod_proxy_ajp: Support unknown HTTP methods. PR 54416. [Rainer Jung] mod_dir: Add support for the value 'disabled' in FallbackResource. [Vincent Deffontaines] mod_ldap: Fix regression in handling "server unavailable" errors on Windows. PR 54140. [Eric Covener] mod_ssl: fix a regression with the string rendering of the "UID" RDN introduced in 2.2.15. PR 54510. [Kaspar Brand] ab: add TLS1.1/TLS1.2 options to -f switch, and adapt output to more accurately report the negotiated protocol. PR 53916. [Nicolás Pernas Maradei , Kaspar Brand] mod_cache: Explicitly allow cache implementations to cache a 206 Partial Response if they so choose to do so. Previously an attempt to cache a 206 was arbitrarily allowed if the response contained an Expires or Cache-Control header, and arbitrarily denied if both headers were missing Currently the disk and memory cache providers do not cache 206 Partial Responses. [Graham Leggett] core: Remove unintentional APR 1.3 dependency introduced with Apache 2.2.22. [Eric Covener] core: Use a TLS 1.0 close_notify alert for internal dummy connection if the chosen listener is configured for https. [Joe Orton] mod_ssl: Add new directive SSLCompression to disable TLS-level compression. PR 53219. [1] requested by Andrew Filonov (freebsd-apache/2012-September/002962.html) with head apache@ Added: head/www/apache22-itk-mpm/files/ - copied unchanged from r313266, head/www/apache22/files/mpm-itk-20110321-01 - copied unchanged from r313266, head/www/apache22/files/mpm-itk-limits - copied unchanged from r313266, head/www/apache22/files/mpm-itk-perdir-regex Directory Properties: head/www/apache22-itk-mpm/files/mpm-itk-20110321-01 (props changed) head/www/apache22-itk-mpm/files/mpm-itk-limits (props changed) head/www/apache22-itk-mpm/files/mpm-itk-perdir-regex (props changed) Deleted: head/www/apache22/files/mpm-itk-20110321-01 head/www/apache22/files/mpm-itk-limits head/www/apache22/files/mpm-itk-perdir-regex Modified: head/www/apache22-itk-mpm/Makefile head/www/apache22/Makefile head/www/apache22/Makefile.modules head/www/apache22/distinfo (contents, props changed) head/www/apache22/files/apache22.in (contents, props changed) Modified: head/www/apache22-itk-mpm/Makefile ============================================================================== --- head/www/apache22-itk-mpm/Makefile Sat Mar 2 19:30:29 2013 (r313286) +++ head/www/apache22-itk-mpm/Makefile Sat Mar 2 19:31:49 2013 (r313287) @@ -1,5 +1,5 @@ # $FreeBSD$ -# + # To build this port with the additional mpm-itk-perdir-regex # patch use -DWITH_ITK_PERDIR_REGEX # @@ -8,7 +8,7 @@ # # Note: # It's not possible to use both patches together -#´ +# # For a quick description take a look into the mpm-itk* patches # in the apache22/files directory @@ -21,4 +21,20 @@ WITH_MPM= itk LATEST_LINK= apache22-${WITH_MPM}-mpm DESCR= ${.CURDIR}/pkg-descr +MPM_ITK_VERSION?= 20110321-01 + +EXTRA_PATCHES+= ${.CURDIR}/files/mpm-itk-${MPM_ITK_VERSION} + +.if defined (WITH_ITK_PERDIR_REGEX) && defined (WITH_ITK_LIMITS) +IGNORE= use only one patch option not both (WITH_ITK_PERDIR_REGEX or WITH_ITK_LIMITS) +.endif + +.if defined (WITH_ITK_PERDIR_REGEX) +EXTRA_PATCHES+= ${.CURDIR}/files/mpm-itk-perdir-regex +.endif + +.if defined (WITH_ITK_LIMITS) +EXTRA_PATCHES+= ${.CURDIR}/files/mpm-itk-limits +.endif + .include "${MASTERDIR}/Makefile" Copied: head/www/apache22-itk-mpm/files/mpm-itk-20110321-01 (from r313266, head/www/apache22/files/mpm-itk-20110321-01) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/apache22-itk-mpm/files/mpm-itk-20110321-01 Sat Mar 2 19:31:49 2013 (r313287, copy of r313266, head/www/apache22/files/mpm-itk-20110321-01) @@ -0,0 +1,2112 @@ +vim: syntax=diff + +Monolithic mpm-itk patch version 2.2.17-01 updated 2011-03-21 + +The Apache 2 ITK MPM + +apache2-mpm-itk (just mpm-itk for short) is an MPM (Multi-Processing Module) +for the Apache web server. mpm-itk allows you to run each of your vhost +under a separate uid and gid . in short, the scripts and configuration files +for one vhost no longer have to be readable for all the other vhosts. + +mpm-itk is based on the traditional prefork MPM, which means it's +non-threaded; in short, this means you can run non-thread-aware code (like +many PHP extensions) without problems. On the other hand, you lose out to +any performance benefit you'd get with threads, of course; you'd have to +decide for yourself if that's worth it or not. You will also take an +additional performance hit over prefork, since there's an extra fork per +request. + +Licensing: + mpm-itk is licensed under the Apache License, version 2.0, + like the rest of Apache. + +For more Informations and Instructions please visit the official webpage. + +WWW: http://mpm-itk.sesse.net/ + +=========================================================================== +unchanged: +--- server/mpm/experimental/itk/Makefile.in ++++ server/mpm/experimental/itk/Makefile.in +@@ -0,0 +1,5 @@ ++ ++LTLIBRARY_NAME = libitk.la ++LTLIBRARY_SOURCES = itk.c ++ ++include $(top_srcdir)/build/ltlib.mk +unchanged: +--- server/mpm/experimental/itk/config.m4 ++++ server/mpm/experimental/itk/config.m4 +@@ -0,0 +1,3 @@ ++if test "$MPM_NAME" = "itk" ; then ++ APACHE_FAST_OUTPUT(server/mpm/$MPM_SUBDIR_NAME/Makefile) ++fi +unchanged: +--- server/mpm/experimental/itk/itk.c ++++ server/mpm/experimental/itk/itk.c +@@ -0,0 +1,1757 @@ ++/* Licensed to the Apache Software Foundation (ASF) under one or more ++ * contributor license agreements. See the NOTICE file distributed with ++ * this work for additional information regarding copyright ownership. ++ * The ASF licenses this file to You under the Apache License, Version 2.0 ++ * (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ * Portions copyright 2005-2009 Steinar H. Gunderson . ++ * Licensed under the same terms as the rest of Apache. ++ * ++ * Portions copyright 2008 Knut Auvor Grythe . ++ * Licensed under the same terms as the rest of Apache. ++ */ ++ ++#include "apr.h" ++#include "apr_portable.h" ++#include "apr_strings.h" ++#include "apr_thread_proc.h" ++#include "apr_signal.h" ++ ++# define _DBG(text,par...) \ ++ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \ ++ "(itkmpm: pid=%d uid=%d, gid=%d) %s(): " text, \ ++ getpid(), getuid(), getgid(), __FUNCTION__, par) ++ ++#define APR_WANT_STDIO ++#define APR_WANT_STRFUNC ++#include "apr_want.h" ++ ++#if APR_HAVE_UNISTD_H ++#include ++#endif ++#if APR_HAVE_SYS_TYPES_H ++#include ++#endif ++ ++#define CORE_PRIVATE ++ ++#include "ap_config.h" ++#include "httpd.h" ++#include "mpm_default.h" ++#include "http_main.h" ++#include "http_log.h" ++#include "http_config.h" ++#include "http_core.h" /* for get_remote_host */ ++#include "http_connection.h" ++#include "http_request.h" /* for ap_hook_post_perdir_config */ ++#include "scoreboard.h" ++#include "ap_mpm.h" ++#include "unixd.h" ++#include "mpm_common.h" ++#include "ap_listen.h" ++#include "ap_mmn.h" ++#include "apr_poll.h" ++ ++#ifdef HAVE_BSTRING_H ++#include /* for IRIX, FD_SET calls bzero() */ ++#endif ++#ifdef HAVE_TIME_H ++#include ++#endif ++#ifdef HAVE_SYS_PROCESSOR_H ++#include /* for bindprocessor() */ ++#endif ++ ++#if HAVE_LIBCAP ++#include ++#endif ++ ++#include ++#include ++ ++/* Limit on the total --- clients will be locked out if more servers than ++ * this are needed. It is intended solely to keep the server from crashing ++ * when things get out of hand. ++ * ++ * We keep a hard maximum number of servers, for two reasons --- first off, ++ * in case something goes seriously wrong, we want to stop the fork bomb ++ * short of actually crashing the machine we're running on by filling some ++ * kernel table. Secondly, it keeps the size of the scoreboard file small ++ * enough that we can read the whole thing without worrying too much about ++ * the overhead. ++ */ ++#ifndef DEFAULT_SERVER_LIMIT ++#define DEFAULT_SERVER_LIMIT 256 ++#endif ++ ++/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT. We want ++ * some sort of compile-time limit to help catch typos. ++ */ ++#ifndef MAX_SERVER_LIMIT ++#define MAX_SERVER_LIMIT 200000 ++#endif ++ ++#ifndef HARD_THREAD_LIMIT ++#define HARD_THREAD_LIMIT 1 ++#endif ++ ++/* config globals */ ++ ++int ap_threads_per_child=0; /* Worker threads per child */ ++static apr_proc_mutex_t *accept_mutex; ++static int ap_daemons_to_start=0; ++static int ap_daemons_min_free=0; ++static int ap_daemons_max_free=0; ++static int ap_daemons_limit=0; /* MaxClients */ ++static int server_limit = DEFAULT_SERVER_LIMIT; ++static int first_server_limit = 0; ++static int changed_limit_at_restart; ++static int mpm_state = AP_MPMQ_STARTING; ++static ap_pod_t *pod; ++ ++/* ++ * The max child slot ever assigned, preserved across restarts. Necessary ++ * to deal with MaxClients changes across AP_SIG_GRACEFUL restarts. We ++ * use this value to optimize routines that have to scan the entire scoreboard. ++ */ ++int ap_max_daemons_limit = -1; ++server_rec *ap_server_conf; ++ ++/* one_process --- debugging mode variable; can be set from the command line ++ * with the -X flag. If set, this gets you the child_main loop running ++ * in the process which originally started up (no detach, no make_child), ++ * which is a pretty nice debugging environment. (You'll get a SIGHUP ++ * early in standalone_main; just continue through. This is the server ++ * trying to kill off any child processes which it might have lying ++ * around --- Apache doesn't keep track of their pids, it just sends ++ * SIGHUP to the process group, ignoring it in the root process. ++ * Continue through and you'll be fine.). ++ */ ++ ++static int one_process = 0; ++ ++static apr_pool_t *pconf; /* Pool for config stuff */ ++static apr_pool_t *pchild; /* Pool for httpd child stuff */ ++ ++static pid_t ap_my_pid; /* it seems silly to call getpid all the time */ ++static pid_t parent_pid; ++#ifndef MULTITHREAD ++static int my_child_num; ++#endif ++ap_generation_t volatile ap_my_generation=0; ++ ++#ifdef TPF ++int tpf_child = 0; ++char tpf_server_name[INETD_SERVNAME_LENGTH+1]; ++#endif /* TPF */ ++ ++static volatile int die_now = 0; ++ ++#define UNSET_NICE_VALUE 100 ++ ++typedef struct ++{ ++ uid_t uid; ++ gid_t gid; ++ char *username; ++ int nice_value; ++} itk_per_dir_conf; ++ ++typedef struct ++{ ++ int max_clients_vhost; ++} itk_server_conf; ++ ++module AP_MODULE_DECLARE_DATA mpm_itk_module; ++ ++#ifdef GPROF ++/* ++ * change directory for gprof to plop the gmon.out file ++ * configure in httpd.conf: ++ * GprofDir $RuntimeDir/ -> $ServerRoot/$RuntimeDir/gmon.out ++ * GprofDir $RuntimeDir/% -> $ServerRoot/$RuntimeDir/gprof.$pid/gmon.out ++ */ ++static void chdir_for_gprof(void) ++{ ++ core_server_config *sconf = ++ ap_get_module_config(ap_server_conf->module_config, &core_module); ++ char *dir = sconf->gprof_dir; ++ const char *use_dir; ++ ++ if(dir) { ++ apr_status_t res; ++ char *buf = NULL ; ++ int len = strlen(sconf->gprof_dir) - 1; ++ if(*(dir + len) == '%') { ++ dir[len] = '\0'; ++ buf = ap_append_pid(pconf, dir, "gprof."); ++ } ++ use_dir = ap_server_root_relative(pconf, buf ? buf : dir); ++ res = apr_dir_make(use_dir, ++ APR_UREAD | APR_UWRITE | APR_UEXECUTE | ++ APR_GREAD | APR_GEXECUTE | ++ APR_WREAD | APR_WEXECUTE, pconf); ++ if(res != APR_SUCCESS && !APR_STATUS_IS_EEXIST(res)) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, res, ap_server_conf, ++ "gprof: error creating directory %s", dir); ++ } ++ } ++ else { ++ use_dir = ap_server_root_relative(pconf, DEFAULT_REL_RUNTIMEDIR); ++ } ++ ++ chdir(use_dir); ++} ++#else ++#define chdir_for_gprof() ++#endif ++ ++/* XXX - I don't know if TPF will ever use this module or not, so leave ++ * the ap_check_signals calls in but disable them - manoj */ ++#define ap_check_signals() ++ ++/* a clean exit from a child with proper cleanup */ ++static void clean_child_exit(int code) __attribute__ ((noreturn)); ++static void clean_child_exit(int code) ++{ ++ mpm_state = AP_MPMQ_STOPPING; ++ ++ if (pchild) { ++ apr_pool_destroy(pchild); ++ } ++ ap_mpm_pod_close(pod); ++ chdir_for_gprof(); ++ exit(code); ++} ++ ++static void accept_mutex_on(void) ++{ ++ apr_status_t rv = apr_proc_mutex_lock(accept_mutex); ++ if (rv != APR_SUCCESS) { ++ const char *msg = "couldn't grab the accept mutex"; ++ ++ if (ap_my_generation != ++ ap_scoreboard_image->global->running_generation) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg); ++ clean_child_exit(0); ++ } ++ else { ++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg); ++ exit(APEXIT_CHILDFATAL); ++ } ++ } ++} ++ ++static void accept_mutex_off(void) ++{ ++ apr_status_t rv = apr_proc_mutex_unlock(accept_mutex); ++ if (rv != APR_SUCCESS) { ++ const char *msg = "couldn't release the accept mutex"; ++ ++ if (ap_my_generation != ++ ap_scoreboard_image->global->running_generation) { ++ ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, NULL, "%s", msg); ++ /* don't exit here... we have a connection to ++ * process, after which point we'll see that the ++ * generation changed and we'll exit cleanly ++ */ ++ } ++ else { ++ ap_log_error(APLOG_MARK, APLOG_EMERG, rv, NULL, "%s", msg); ++ exit(APEXIT_CHILDFATAL); ++ } ++ } ++} ++ ++/* On some architectures it's safe to do unserialized accept()s in the single ++ * Listen case. But it's never safe to do it in the case where there's ++ * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT ++ * when it's safe in the single Listen case. ++ */ ++#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT ++#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0) ++#else ++#define SAFE_ACCEPT(stmt) do {stmt;} while(0) ++#endif ++ ++AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) ++{ ++ switch(query_code){ ++ case AP_MPMQ_MAX_DAEMON_USED: ++ *result = ap_daemons_limit; ++ return APR_SUCCESS; ++ case AP_MPMQ_IS_THREADED: ++ *result = AP_MPMQ_NOT_SUPPORTED; ++ return APR_SUCCESS; ++ case AP_MPMQ_IS_FORKED: ++ *result = AP_MPMQ_DYNAMIC; ++ return APR_SUCCESS; ++ case AP_MPMQ_HARD_LIMIT_DAEMONS: ++ *result = server_limit; ++ return APR_SUCCESS; ++ case AP_MPMQ_HARD_LIMIT_THREADS: ++ *result = HARD_THREAD_LIMIT; ++ return APR_SUCCESS; ++ case AP_MPMQ_MAX_THREADS: ++ *result = 0; ++ return APR_SUCCESS; ++ case AP_MPMQ_MIN_SPARE_DAEMONS: ++ *result = ap_daemons_min_free; ++ return APR_SUCCESS; ++ case AP_MPMQ_MIN_SPARE_THREADS: ++ *result = 0; ++ return APR_SUCCESS; ++ case AP_MPMQ_MAX_SPARE_DAEMONS: ++ *result = ap_daemons_max_free; ++ return APR_SUCCESS; ++ case AP_MPMQ_MAX_SPARE_THREADS: ++ *result = 0; ++ return APR_SUCCESS; ++ case AP_MPMQ_MAX_REQUESTS_DAEMON: ++ *result = ap_max_requests_per_child; ++ return APR_SUCCESS; ++ case AP_MPMQ_MAX_DAEMONS: ++ *result = server_limit; ++ return APR_SUCCESS; ++ case AP_MPMQ_MPM_STATE: ++ *result = mpm_state; ++ return APR_SUCCESS; ++ } ++ return APR_ENOTIMPL; ++} ++ ++#if defined(NEED_WAITPID) ++/* ++ Systems without a real waitpid sometimes lose a child's exit while waiting ++ for another. Search through the scoreboard for missing children. ++ */ ++int reap_children(int *exitcode, apr_exit_why_e *status) ++{ ++ int n, pid; ++ ++ for (n = 0; n < ap_max_daemons_limit; ++n) { ++ if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD && ++ kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) { ++ ap_update_child_status_from_indexes(n, 0, SERVER_DEAD, NULL); ++ /* just mark it as having a successful exit status */ ++ *status = APR_PROC_EXIT; ++ *exitcode = 0; ++ return(pid); ++ } ++ } ++ return 0; ++} ++#endif ++ ++/***************************************************************** ++ * Connection structures and accounting... ++ */ ++ ++static void just_die(int sig) ++{ ++ clean_child_exit(0); ++} ++ ++static void stop_listening(int sig) ++{ ++ ap_close_listeners(); ++ ++ /* For a graceful stop, we want the child to exit when done */ ++ die_now = 1; ++} ++ ++/* volatile just in case */ ++static int volatile shutdown_pending; ++static int volatile restart_pending; ++static int volatile is_graceful; ++ ++static void sig_term(int sig) ++{ ++ if (shutdown_pending == 1) { ++ /* Um, is this _probably_ not an error, if the user has ++ * tried to do a shutdown twice quickly, so we won't ++ * worry about reporting it. ++ */ ++ return; ++ } ++ shutdown_pending = 1; ++ is_graceful = (sig == AP_SIG_GRACEFUL_STOP); ++} ++ ++/* restart() is the signal handler for SIGHUP and AP_SIG_GRACEFUL ++ * in the parent process, unless running in ONE_PROCESS mode ++ */ ++static void restart(int sig) ++{ ++ if (restart_pending == 1) { ++ /* Probably not an error - don't bother reporting it */ ++ return; ++ } ++ restart_pending = 1; ++ is_graceful = (sig == AP_SIG_GRACEFUL); ++} ++ ++static void set_signals(void) ++{ ++#ifndef NO_USE_SIGACTION ++ struct sigaction sa; ++#endif ++ ++ if (!one_process) { ++ ap_fatal_signal_setup(ap_server_conf, pconf); ++ } ++ ++#ifndef NO_USE_SIGACTION ++ sigemptyset(&sa.sa_mask); ++ sa.sa_flags = 0; ++ ++ sa.sa_handler = sig_term; ++ if (sigaction(SIGTERM, &sa, NULL) < 0) ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGTERM)"); ++#ifdef AP_SIG_GRACEFUL_STOP ++ if (sigaction(AP_SIG_GRACEFUL_STOP, &sa, NULL) < 0) ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, ++ "sigaction(" AP_SIG_GRACEFUL_STOP_STRING ")"); ++#endif ++#ifdef SIGINT ++ if (sigaction(SIGINT, &sa, NULL) < 0) ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGINT)"); ++#endif ++#ifdef SIGXCPU ++ sa.sa_handler = SIG_DFL; ++ if (sigaction(SIGXCPU, &sa, NULL) < 0) ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXCPU)"); ++#endif ++#ifdef SIGXFSZ ++ sa.sa_handler = SIG_DFL; ++ if (sigaction(SIGXFSZ, &sa, NULL) < 0) ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGXFSZ)"); ++#endif ++#ifdef SIGPIPE ++ sa.sa_handler = SIG_IGN; ++ if (sigaction(SIGPIPE, &sa, NULL) < 0) ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGPIPE)"); ++#endif ++ ++ /* we want to ignore HUPs and AP_SIG_GRACEFUL while we're busy ++ * processing one ++ */ ++ sigaddset(&sa.sa_mask, SIGHUP); ++ sigaddset(&sa.sa_mask, AP_SIG_GRACEFUL); ++ sa.sa_handler = restart; ++ if (sigaction(SIGHUP, &sa, NULL) < 0) ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(SIGHUP)"); ++ if (sigaction(AP_SIG_GRACEFUL, &sa, NULL) < 0) ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ap_server_conf, "sigaction(" AP_SIG_GRACEFUL_STRING ")"); ++#else ++ if (!one_process) { ++#ifdef SIGXCPU ++ apr_signal(SIGXCPU, SIG_DFL); ++#endif /* SIGXCPU */ ++#ifdef SIGXFSZ ++ apr_signal(SIGXFSZ, SIG_DFL); ++#endif /* SIGXFSZ */ ++ } ++ ++ apr_signal(SIGTERM, sig_term); ++#ifdef SIGHUP ++ apr_signal(SIGHUP, restart); ++#endif /* SIGHUP */ ++#ifdef AP_SIG_GRACEFUL ++ apr_signal(AP_SIG_GRACEFUL, restart); ++#endif /* AP_SIG_GRACEFUL */ ++#ifdef AP_SIG_GRACEFUL_STOP ++ apr_signal(AP_SIG_GRACEFUL_STOP, sig_term); ++#endif /* AP_SIG_GRACEFUL */ ++#ifdef SIGPIPE ++ apr_signal(SIGPIPE, SIG_IGN); ++#endif /* SIGPIPE */ ++ ++#endif ++} ++ ++/***************************************************************** ++ * Child process main loop. ++ * The following vars are static to avoid getting clobbered by longjmp(); ++ * they are really private to child_main. ++ */ ++ ++static int requests_this_child; ++static int num_listensocks = 0; ++ ++ ++int ap_graceful_stop_signalled(void) ++{ ++ /* not ever called anymore... */ ++ return 0; ++} ++ ++ ++static void child_main(int child_num_arg) ++{ ++ apr_pool_t *ptrans; ++ apr_allocator_t *allocator; ++ apr_status_t status; ++ int i; ++ ap_listen_rec *lr; ++ apr_pollset_t *pollset; ++ ap_sb_handle_t *sbh; ++ apr_bucket_alloc_t *bucket_alloc; ++ int last_poll_idx = 0; ++ ++#if HAVE_LIBCAP ++ cap_t caps; ++ cap_value_t suidcaps[] = { ++ CAP_SETUID, ++ CAP_SETGID, ++ CAP_DAC_READ_SEARCH, ++ CAP_SYS_NICE, ++ }; ++#endif ++ ++ mpm_state = AP_MPMQ_STARTING; /* for benefit of any hooks that run as this ++ * child initializes ++ */ ++ ++ my_child_num = child_num_arg; ++ ap_my_pid = getpid(); ++ requests_this_child = 0; ++ ++ ap_fatal_signal_child_setup(ap_server_conf); ++ ++ /* Get a sub context for global allocations in this child, so that ++ * we can have cleanups occur when the child exits. ++ */ ++ apr_allocator_create(&allocator); ++ apr_allocator_max_free_set(allocator, ap_max_mem_free); ++ apr_pool_create_ex(&pchild, pconf, NULL, allocator); ++ apr_allocator_owner_set(allocator, pchild); ++ ++ apr_pool_create(&ptrans, pchild); ++ apr_pool_tag(ptrans, "transaction"); ++ ++ /* needs to be done before we switch UIDs so we have permissions */ ++ ap_reopen_scoreboard(pchild, NULL, 0); ++ status = apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild); ++ if (status != APR_SUCCESS) { ++ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, ++ "Couldn't initialize cross-process lock in child " ++ "(%s) (%d)", ap_lock_fname, ap_accept_lock_mech); ++ clean_child_exit(APEXIT_CHILDFATAL); ++ } ++ ++ ap_run_child_init(pchild, ap_server_conf); ++ ++ ap_create_sb_handle(&sbh, pchild, my_child_num, 0); ++ ++ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL); ++ ++ /* Set up the pollfd array */ ++ status = apr_pollset_create(&pollset, num_listensocks, pchild, 0); ++ if (status != APR_SUCCESS) { ++ ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, ++ "Couldn't create pollset in child; check system or user limits"); ++ clean_child_exit(APEXIT_CHILDSICK); /* assume temporary resource issue */ ++ } ++ ++ for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) { ++ apr_pollfd_t pfd = { 0 }; ++ ++ pfd.desc_type = APR_POLL_SOCKET; ++ pfd.desc.s = lr->sd; ++ pfd.reqevents = APR_POLLIN; ++ pfd.client_data = lr; ++ ++ /* ### check the status */ ++ (void) apr_pollset_add(pollset, &pfd); ++ } ++ ++#if HAVE_LIBCAP ++ /* Drop as many privileges as we can. We'll still ++ * access files with uid=0, and we can setuid() to anything, but ++ * at least there's tons of other evilness (like loading kernel ++ * modules) we can't do directly. (The setuid() capability will ++ * go away automatically when we setuid() or exec() -- the former ++ * is likely to come first.) ++ */ ++ caps = cap_init(); ++ cap_clear(caps); ++ cap_set_flag(caps, CAP_PERMITTED, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET); ++ cap_set_flag(caps, CAP_EFFECTIVE, sizeof(suidcaps)/sizeof(cap_value_t), suidcaps, CAP_SET); ++ cap_set_proc(caps); ++ cap_free(caps); ++#endif ++ ++ mpm_state = AP_MPMQ_RUNNING; ++ ++ bucket_alloc = apr_bucket_alloc_create(pchild); ++ ++ /* die_now is set when AP_SIG_GRACEFUL is received in the child; ++ * shutdown_pending is set when SIGTERM is received when running ++ * in single process mode. */ ++ while (!die_now && !shutdown_pending) { ++ conn_rec *current_conn; ++ void *csd; ++ ++ /* ++ * (Re)initialize this child to a pre-connection state. ++ */ ++ ++ apr_pool_clear(ptrans); ++ ++ if ((ap_max_requests_per_child > 0 ++ && requests_this_child++ >= ap_max_requests_per_child)) { ++ clean_child_exit(0); ++ } ++ ++ (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL); ++ ++ /* ++ * Wait for an acceptable connection to arrive. ++ */ ++ ++ /* Lock around "accept", if necessary */ ++ SAFE_ACCEPT(accept_mutex_on()); ++ ++ if (num_listensocks == 1) { ++ /* There is only one listener record, so refer to that one. */ ++ lr = ap_listeners; ++ } ++ else { ++ /* multiple listening sockets - need to poll */ ++ for (;;) { ++ apr_int32_t numdesc; ++ const apr_pollfd_t *pdesc; ++ ++ /* check for termination first so we don't sleep for a while in ++ * poll if already signalled ++ */ ++ if (one_process && shutdown_pending) { ++ SAFE_ACCEPT(accept_mutex_off()); ++ return; ++ } ++ else if (die_now) { ++ /* In graceful stop/restart; drop the mutex ++ * and terminate the child. */ ++ SAFE_ACCEPT(accept_mutex_off()); ++ clean_child_exit(0); ++ } ++ /* timeout == 10 seconds to avoid a hang at graceful restart/stop ++ * caused by the closing of sockets by the signal handler ++ */ ++ status = apr_pollset_poll(pollset, apr_time_from_sec(10), ++ &numdesc, &pdesc); ++ if (status != APR_SUCCESS) { ++ if (APR_STATUS_IS_TIMEUP(status) || ++ APR_STATUS_IS_EINTR(status)) { ++ continue; ++ } ++ /* Single Unix documents select as returning errnos ++ * EBADF, EINTR, and EINVAL... and in none of those ++ * cases does it make sense to continue. In fact ++ * on Linux 2.0.x we seem to end up with EFAULT ++ * occasionally, and we'd loop forever due to it. ++ */ ++ ap_log_error(APLOG_MARK, APLOG_ERR, status, ++ ap_server_conf, "apr_pollset_poll: (listen)"); ++ SAFE_ACCEPT(accept_mutex_off()); ++ clean_child_exit(1); ++ } ++ ++ /* We can always use pdesc[0], but sockets at position N ++ * could end up completely starved of attention in a very ++ * busy server. Therefore, we round-robin across the ++ * returned set of descriptors. While it is possible that ++ * the returned set of descriptors might flip around and ++ * continue to starve some sockets, we happen to know the ++ * internal pollset implementation retains ordering ++ * stability of the sockets. Thus, the round-robin should ++ * ensure that a socket will eventually be serviced. ++ */ ++ if (last_poll_idx >= numdesc) ++ last_poll_idx = 0; ++ ++ /* Grab a listener record from the client_data of the poll ++ * descriptor, and advance our saved index to round-robin ++ * the next fetch. ++ * ++ * ### hmm... this descriptor might have POLLERR rather ++ * ### than POLLIN ++ */ ++ lr = pdesc[last_poll_idx++].client_data; ++ goto got_fd; ++ } ++ } ++ got_fd: ++ /* if we accept() something we don't want to die, so we have to ++ * defer the exit ++ */ ++ status = lr->accept_func(&csd, lr, ptrans); ++ ++ SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */ ++ ++ if (status == APR_EGENERAL) { ++ /* resource shortage or should-not-occur occurred */ ++ clean_child_exit(1); ++ } ++ else if (status != APR_SUCCESS) { ++ continue; ++ } ++ ++ /* ++ * We now have a connection, so set it up with the appropriate ++ * socket options, file descriptors, and read/write buffers. ++ */ ++ ++ { ++ pid_t pid = fork(), child_pid; ++ int status; ++ switch (pid) { ++ case -1: ++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "fork: Unable to fork new process"); ++ break; ++ case 0: /* child */ ++ apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild); ++ current_conn = ap_run_create_connection(ptrans, ap_server_conf, csd, my_child_num, sbh, bucket_alloc); ++ if (current_conn) { ++ ap_process_connection(current_conn, csd); ++ ap_lingering_close(current_conn); ++ } ++ exit(0); ++ default: /* parent; just wait for child to be done */ ++ do { ++ child_pid = waitpid(pid, &status, 0); ++ } while (child_pid == -1 && errno == EINTR); ++ ++ if (child_pid != pid || !WIFEXITED(status)) { ++ if (WIFSIGNALED(status)) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child died with signal %u", WTERMSIG(status)); ++ } else if (WEXITSTATUS(status) != 0) { ++ ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, "child exited with non-zero exit status %u", WEXITSTATUS(status)); ++ } else { ++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, NULL, "waitpid() failed"); ++ } ++ clean_child_exit(1); ++ } ++ break; ++ } ++ } ++ ++ /* Check the pod and the generation number after processing a ++ * connection so that we'll go away if a graceful restart occurred ++ * while we were processing the connection or we are the lucky ++ * idle server process that gets to die. ++ */ ++ if (ap_mpm_pod_check(pod) == APR_SUCCESS) { /* selected as idle? */ ++ die_now = 1; ++ } ++ else if (ap_my_generation != ++ ap_scoreboard_image->global->running_generation) { /* restart? */ ++ /* yeah, this could be non-graceful restart, in which case the ++ * parent will kill us soon enough, but why bother checking? ++ */ ++ die_now = 1; ++ } ++ ++ /* if we have already setuid(), die (we can't be used anyhow) */ ++ if (getuid()) ++ die_now = 1; ++ } ++ /* This apr_pool_clear call is redundant, should be redundant, but compensates ++ * a flaw in the apr reslist code. This should be removed once that flaw has ++ * been addressed. ++ */ ++ apr_pool_clear(ptrans); ++ clean_child_exit(0); ++} ++ ++ ++static int make_child(server_rec *s, int slot) ++{ ++ int pid; ++ ++ if (slot + 1 > ap_max_daemons_limit) { ++ ap_max_daemons_limit = slot + 1; ++ } ++ ++ if (one_process) { ++ apr_signal(SIGHUP, sig_term); ++ /* Don't catch AP_SIG_GRACEFUL in ONE_PROCESS mode :) */ ++ apr_signal(SIGINT, sig_term); ++#ifdef SIGQUIT ++ apr_signal(SIGQUIT, SIG_DFL); ++#endif ++ apr_signal(SIGTERM, sig_term); ++ child_main(slot); ++ return 0; ++ } ++ ++ (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING, ++ (request_rec *) NULL); ++ ++ ++#ifdef _OSD_POSIX ++ /* BS2000 requires a "special" version of fork() before a setuid() call */ ++ if ((pid = os_fork(unixd_config.user_name)) == -1) { ++#elif defined(TPF) ++ if ((pid = os_fork(s, slot)) == -1) { ++#else ++ if ((pid = fork()) == -1) { ++#endif ++ ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "fork: Unable to fork new process"); ++ ++ /* fork didn't succeed. Fix the scoreboard or else ++ * it will say SERVER_STARTING forever and ever ++ */ ++ (void) ap_update_child_status_from_indexes(slot, 0, SERVER_DEAD, ++ (request_rec *) NULL); ++ ++ /* In case system resources are maxxed out, we don't want ++ * Apache running away with the CPU trying to fork over and ++ * over and over again. ++ */ ++ sleep(10); ++ ++ return -1; ++ } ++ ++ if (!pid) { ++#ifdef HAVE_BINDPROCESSOR ++ /* by default AIX binds to a single processor ++ * this bit unbinds children which will then bind to another cpu ++ */ ++ int status = bindprocessor(BINDPROCESS, (int)getpid(), ++ PROCESSOR_CLASS_ANY); ++ if (status != OK) { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ++ ap_server_conf, "processor unbind failed %d", status); ++ } ++#endif ++ RAISE_SIGSTOP(MAKE_CHILD); ++ AP_MONCONTROL(1); ++ /* Disable the parent's signal handlers and set up proper handling in ++ * the child. ++ */ ++ apr_signal(SIGHUP, just_die); ++ apr_signal(SIGTERM, just_die); ++ /* The child process just closes listeners on AP_SIG_GRACEFUL. ++ * The pod is used for signalling the graceful restart. ++ */ ++ apr_signal(AP_SIG_GRACEFUL, stop_listening); ++ child_main(slot); ++ } ++ ++ ap_scoreboard_image->parent[slot].pid = pid; ++ ++ return 0; ++} ++ ++ ++/* start up a bunch of children */ ++static void startup_children(int number_to_start) ++{ ++ int i; ++ ++ for (i = 0; number_to_start && i < ap_daemons_limit; ++i) { ++ if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) { ++ continue; ++ } ++ if (make_child(ap_server_conf, i) < 0) { ++ break; ++ } ++ --number_to_start; ++ } ++} ++ ++ ++/* ++ * idle_spawn_rate is the number of children that will be spawned on the ++ * next maintenance cycle if there aren't enough idle servers. It is ++ * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by ++ * without the need to spawn. ++ */ ++static int idle_spawn_rate = 1; ++#ifndef MAX_SPAWN_RATE ++#define MAX_SPAWN_RATE (32) ++#endif ++static int hold_off_on_exponential_spawning; ++ ++static void perform_idle_server_maintenance(apr_pool_t *p) ++{ ++ int i; ++ int to_kill; ++ int idle_count; ++ worker_score *ws; ++ int free_length; ++ int free_slots[MAX_SPAWN_RATE]; ++ int last_non_dead; ++ int total_non_dead; ++ ++ /* initialize the free_list */ ++ free_length = 0; ++ ++ to_kill = -1; ++ idle_count = 0; ++ last_non_dead = -1; ++ total_non_dead = 0; ++ ++ for (i = 0; i < ap_daemons_limit; ++i) { ++ int status; ++ ++ if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***