diff options
-rw-r--r-- | 2.0/init/apache2.confd | 19 | ||||
-rwxr-xr-x | 2.0/init/apache2.initd | 112 | ||||
-rw-r--r-- | 2.0/patches/01_all_gentoo_base.patch | 51 | ||||
-rw-r--r-- | 2.0/patches/03_all_gentoo-apache-tools.patch | 68 | ||||
-rw-r--r-- | 2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch | 332 | ||||
-rw-r--r-- | 2.0/patches/80_all_CVE-2007-5752.patch | 42 | ||||
-rw-r--r-- | 2.0/patches/81_all_CVE-2007-3304.patch | 16 | ||||
-rw-r--r-- | 2.0/patches/82_all_CVE-2007-1863.patch | 75 | ||||
-rw-r--r-- | 2.0/patches/83_all_CVE-2007-2874.patch | 88 | ||||
-rw-r--r-- | 2.2/conf/apache2-builtin-mods | 4 | ||||
-rw-r--r-- | 2.2/patches/04_all_mod_dbd_r553563.patch | 1279 | ||||
-rw-r--r-- | 2.2/patches/20_all_peruser_0.2.2.patch (renamed from 2.2/patches/20_all_peruser_0.2.1.patch) | 160 | ||||
-rw-r--r-- | 2.2/patches/21_all_itk_20070425-00.patch | 18 | ||||
-rw-r--r-- | 2.2/patches/80_all_CVE-2006-5752.patch | 40 | ||||
-rw-r--r-- | 2.2/patches/81_all_CVE-2007-1862.patch | 51 | ||||
-rw-r--r-- | 2.2/patches/82_all_CVE-2007-1863.patch | 74 | ||||
-rw-r--r-- | 2.2/patches/83_all_CVE-2007-3304.patch | 261 |
17 files changed, 276 insertions, 2414 deletions
diff --git a/2.0/init/apache2.confd b/2.0/init/apache2.confd index 0b5b028..a272d73 100644 --- a/2.0/init/apache2.confd +++ b/2.0/init/apache2.confd @@ -37,9 +37,16 @@ APACHE2_OPTS="-D DEFAULT_VHOST" # They are normally dumped to your terminal. #STARTUPERRORLOG="/var/log/apache2/startuperror.log" -# Environment variables to keep -# All environment variables are cleared from apache -# Use this to preserve some of them -# NOTE!!! It's very important that this contains PATH -# TODO: Phase this out in favor of /etc/conf.d/env_whitelist -#KEEPENV="PATH" +# A command that outputs a formatted text version of the HTML at the URL +# of the command line. Designed for lynx, however other programs may work. +#LYNX="lynx -dump" + +# The URL to your server's mod_status status page. +# Required for status and fullstatus +#STATUSURL="http://localhost/server-status" + +# Method to use when reloading the server +# Valid options are 'restart' and 'graceful' +# See http://httpd.apache.org/docs/2.2/stopping.html for information on +# what they do and how they differ. +#RELOAD_TYPE="graceful" diff --git a/2.0/init/apache2.initd b/2.0/init/apache2.initd index 92aaf81..5f72d30 100755 --- a/2.0/init/apache2.initd +++ b/2.0/init/apache2.initd @@ -1,38 +1,8 @@ #!/sbin/runscript -# Copyright 1999-2005 Gentoo Foundation +# Copyright 1999-2007 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -opts="${opts} reload configtest" - -# TODO -# Remove all the enviroment crap, as it's not needed after baselayout 1.12.0. -# There are still people using older versions, baselayout 1.12.0 was first -# stable with 2006.1, so we need to wait some time before doing that. -clear_env_except() { - - local save_env=$1 - shift; - - curr_env=$(env | sed 's/=.*//') - - for env_var in ${curr_env}; do - local save=0 - for save_var in ${save_env}; do - if [[ "${env_var}" == "${save_var}" ]]; then - save=1 - fi - done - - if [[ "${save}" == "0" ]]; then - unset_vars="${unset_vars} -u ${env_var}" - fi - done - - env ${unset_vars} $@ -} - - - +opts="configtest fullstatus graceful gracefulstop modules reload" depend() { need net @@ -47,38 +17,32 @@ configtest() { } checkconfig() { - SERVERROOT="${SERVERROOT:-/usr/lib/apache2}" if [ ! -d ${SERVERROOT} ]; then eerror "SERVERROOT does not exist: ${SERVERROOT}" return 1 fi - + CONFIGFILE="${CONFIGFILE:-/etc/apache2/httpd.conf}" - [ ${CONFIGFILE:0:1} != "/" ] && CONFIGFILE="${SERVERROOT}/${CONFIGFILE}" + [ "${CONFIGFILE#/}" = "${CONFIGFILE}" ] && CONFIGFILE="${SERVERROOT}/${CONFIGFILE}" if [ ! -r "${CONFIGFILE}" ]; then eerror "Unable to read configuration file: ${CONFIGFILE}" return 1 fi - APACHE2_OPTS="${APACHE2_OPTS} -d ${SERVERROOT}" APACHE2_OPTS="${APACHE2_OPTS} -f ${CONFIGFILE}" [ -n "${STARTUPERRORLOG}" ] && APACHE2_OPTS="${APACHE2_OPTS} -E ${STARTUPERRORLOG}" - # set a sane default for KEEPENV - KEEPENV=${KEEPENV:-PATH} - APACHE2="/usr/sbin/apache2" - - # TODO kill the environment crap... see note above - clear_env_except "${KEEPENV}" ${APACHE2} ${APACHE2_OPTS} -t 1>/dev/null 2>&1 + + ${APACHE2} ${APACHE2_OPTS} -t 1>/dev/null 2>&1 ret=$? if [ $ret -ne 0 ]; then eerror "Apache2 has detected a syntax error in your configuration files:" ${APACHE2} ${APACHE2_OPTS} -t fi - + return $ret } @@ -86,22 +50,72 @@ start() { checkconfig || return 1 ebegin "Starting apache2" [ -f /var/log/apache2/ssl_scache ] && rm /var/log/apache2/ssl_scache - - # TODO kill the environment crap... see note above - clear_env_except "${KEEPENV}" /sbin/start-stop-daemon --start --exec ${APACHE2} --pidfile /var/run/apache2.pid -- ${APACHE2_OPTS} -k start + + start-stop-daemon --start --exec ${APACHE2} -- ${APACHE2_OPTS} -k start eend $? } stop() { checkconfig || return 1 ebegin "Stopping apache2" - /sbin/start-stop-daemon --stop --retry -TERM/5/-TERM/5/-KILL/5 --exec ${APACHE2} --pidfile /var/run/apache2.pid + start-stop-daemon --stop --retry -TERM/5/-KILL/5 --exec ${APACHE2} --pidfile /var/run/apache2.pid eend $? } reload() { + RELOAD_TYPE="${RELOAD_TYPE:-graceful}" + checkconfig || return 1 - ebegin "Doing a graceful restart of apache2" - /sbin/start-stop-daemon --stop --signal USR1 --exec ${APACHE2} --pidfile /var/run/apache2.pid + if [ "${RELOAD_TYPE}" = "restart" ]; then + ebegin "Restarting apache2" + start-stop-daemon --stop --oknodo --signal HUP --exec ${APACHE2} --pidfile /var/run/apache2.pid + eend $? + elif [ "${RELOAD_TYPE}" = "graceful" ]; then + ebegin "Gracefully restarting apache2" + start-stop-daemon --stop --oknodo --signal USR1 --exec ${APACHE2} --pidfile /var/run/apache2.pid + eend $? + else + eerror "${RELOAD_TYPE} is not a valid RELOAD_TYPE. Please edit /etc/conf.d/apache2" + fi +} + +graceful() { + checkconfig || return 1 + ebegin "Gracefully restarting apache2" + start-stop-daemon --stop --signal USR1 --exec ${APACHE2} --pidfile /var/run/apache2.pid + eend $? +} + +gracefulstop() { + checkconfig || return 1 + + # zap! + if service_started "${myservice}"; then + mark_service_stopped "${myservice}" + fi + + ebegin "Gracefully stopping apache2" + # 28 is SIGWINCH + start-stop-daemon --stop --signal 28 --exec ${APACHE2} --pidfile /var/run/apache2.pid eend $? } + +modules() { + checkconfig || return 1 + + ${APACHE2} ${APACHE2_OPTS} -M 2>&1 +} + +status() { + LYNX="${LYNX:-lynx -dump}" + STATUSURL="${STATUSURL:-http://localhost/server-status}" + + ${LYNX} ${STATUSURL} | awk ' /process$/ { print; exit } { print } ' +} + +fullstatus() { + LYNX="${LYNX:-lynx -dump}" + STATUSURL="${STATUSURL:-http://localhost/server-status}" + + ${LYNX} ${STATUSURL} +} diff --git a/2.0/patches/01_all_gentoo_base.patch b/2.0/patches/01_all_gentoo_base.patch index bf27f0b..30c17ea 100644 --- a/2.0/patches/01_all_gentoo_base.patch +++ b/2.0/patches/01_all_gentoo_base.patch @@ -4,8 +4,9 @@ modules/ssl/ssl_engine_mutex.c | 2 ++ server/Makefile.in | 3 +++ server/core.c | 2 +- + support/apachectl.in | 22 +++++++++++++++++++--- support/apxs.in | 13 ------------- - 6 files changed, 8 insertions(+), 16 deletions(-) + 7 files changed, 27 insertions(+), 19 deletions(-) --- a/Makefile.in +++ b/Makefile.in @@ -25,7 +26,7 @@ /* The path to the suExec wrapper, can be overridden in Configuration */ #ifndef SUEXEC_BIN -#define SUEXEC_BIN HTTPD_ROOT "/bin/suexec" -+#define SUEXEC_BIN "/usr/sbin/suexec" ++#define SUEXEC_BIN "/usr/sbin/suexec2" #endif /* The timeout for waiting for messages */ @@ -63,6 +64,52 @@ } /* +--- a/support/apachectl.in ++++ b/support/apachectl.in +@@ -41,17 +41,25 @@ ARGV="$@" + # -------------------- -------------------- + # + # the path to your httpd binary, including options if necessary +-HTTPD='@exp_sbindir@/@progname@' ++. /etc/conf.d/apache2 ++if [ -n ${MPM} ] && [ -x @exp_sbindir@/@progname@.${MPM} ]; then ++ HTTPD="@exp_sbindir@/@progname@.${MPM} ${APACHE2_OPTS}" ++else ++ HTTPD="@exp_sbindir@/@progname@ ${APACHE2_OPTS}" ++fi + # + # pick up any necessary environment variables +-if test -f @exp_sbindir@/envvars; then +- . @exp_sbindir@/envvars ++if test -f @exp_installbuilddir@/envvars; then ++ . @exp_installbuilddir@/envvars + fi + # + # a command that outputs a formatted text version of the HTML at the + # url given on the command line. Designed for lynx, however other + # programs may work. + LYNX="lynx -dump" ++if ! type -p lynx 2>&1 >/dev/null; then ++ LYNX=no ++fi + # + # the URL to your server's mod_status status page. If you do not + # have one, then status and fullstatus will not work. +@@ -75,6 +83,14 @@ if [ "x$ARGV" = "x" ] ; then + ARGV="-h" + fi + ++if [ "${LYNX}" = "no" ] && [ "${ARGV}" = "status" -o "${ARGV}" = "fullstatus" ]; then ++ echo >&2 "lynx not found!" ++ echo >&2 "" ++ echo >&2 "You need to emerge 'www-client/lynx' for status monitoring via the" ++ echo >&2 "'status' and 'fullstatus' commands to work." ++ exit 1 ++fi ++ + case $ARGV in + start|stop|restart|graceful) + $HTTPD -k $ARGV --- a/support/apxs.in +++ b/support/apxs.in @@ -199,19 +199,6 @@ if ($0 =~ m:support/apxs$:) { diff --git a/2.0/patches/03_all_gentoo-apache-tools.patch b/2.0/patches/03_all_gentoo-apache-tools.patch deleted file mode 100644 index e4c62e1..0000000 --- a/2.0/patches/03_all_gentoo-apache-tools.patch +++ /dev/null @@ -1,68 +0,0 @@ ---- - Makefile.in | 10 ++++++++-- - support/Makefile.in | 16 +++------------- - 2 files changed, 11 insertions(+), 15 deletions(-) - ---- a/Makefile.in -+++ b/Makefile.in -@@ -183,14 +183,20 @@ install-include: - @cp -p $(srcdir)/os/$(OS_DIR)/*.h $(DESTDIR)$(includedir) - @chmod 644 $(DESTDIR)$(includedir)/*.h - -+MAN1= -+MAN8=httpd.8 suexec.8 apxs.8 - install-man: - @echo Installing man pages and online manual - @test -d $(DESTDIR)$(mandir) || $(MKINSTALLDIRS) $(DESTDIR)$(mandir) - @test -d $(DESTDIR)$(mandir)/man1 || $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man1 - @test -d $(DESTDIR)$(mandir)/man8 || $(MKINSTALLDIRS) $(DESTDIR)$(mandir)/man8 - @test -d $(DESTDIR)$(manualdir) || $(MKINSTALLDIRS) $(DESTDIR)$(manualdir) -- @cp -p $(top_srcdir)/docs/man/*.1 $(DESTDIR)$(mandir)/man1 -- @cp -p $(top_srcdir)/docs/man/*.8 $(DESTDIR)$(mandir)/man8 -+ @for i in $(MAN1) ; do \ -+ cp -p $(top_srcdir)/docs/man/$$i $(DESTDIR)$(mandir)/man1; \ -+ done -+ @for i in $(MAN8) ; do \ -+ cp -p $(top_srcdir)/docs/man/$$i $(DESTDIR)$(mandir)/man8; \ -+ done - @(cd $(top_srcdir)/docs/manual && cp -rp * $(DESTDIR)$(manualdir)) - @(cd $(DESTDIR)$(manualdir) && find . -name ".svn" -type d -print | xargs rm -rf 2>/dev/null ) || true - ---- a/support/Makefile.in -+++ b/support/Makefile.in -@@ -1,9 +1,8 @@ --DISTCLEAN_TARGETS = apxs apachectl dbmmanage log_server_status \ -- logresolve.pl phf_abuse_log.cgi split-logfile envvars-std -+DISTCLEAN_TARGETS = apxs - - CLEAN_TARGETS = suexec - --PROGRAMS = htpasswd htdigest rotatelogs logresolve ab checkgid htdbm httxt2dbm -+PROGRAMS = apxs - TARGETS = $(PROGRAMS) - - PROGRAM_LDADD = $(UTIL_LDFLAGS) $(PROGRAM_DEPENDENCIES) $(EXTRA_LIBS) $(AP_LIBS) -@@ -12,22 +11,13 @@ PROGRAM_DEPENDENCIES = - include $(top_builddir)/build/rules.mk - - install: -- @test -d $(DESTDIR)$(bindir) || $(MKINSTALLDIRS) $(DESTDIR)$(bindir) - @test -d $(DESTDIR)$(sbindir) || $(MKINSTALLDIRS) $(DESTDIR)$(sbindir) -- @test -d $(DESTDIR)$(libexecdir) || $(MKINSTALLDIRS) $(DESTDIR)$(libexecdir) -- @cp -p $(top_builddir)/server/httpd.exp $(DESTDIR)$(libexecdir) -- @for i in apxs apachectl dbmmanage; do \ -+ @for i in $(PROGRAMS) ; do \ - if test -f "$(builddir)/$$i"; then \ - cp -p $$i $(DESTDIR)$(sbindir); \ - chmod 755 $(DESTDIR)$(sbindir)/$$i; \ - fi ; \ - done -- @if test -f "$(builddir)/envvars-std"; then \ -- cp -p envvars-std $(DESTDIR)$(sbindir); \ -- if test ! -f $(DESTDIR)$(sbindir)/envvars; then \ -- cp -p envvars-std $(DESTDIR)$(sbindir)/envvars ; \ -- fi ; \ -- fi - - htpasswd_OBJECTS = htpasswd.lo - htpasswd: $(htpasswd_OBJECTS) diff --git a/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch b/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch deleted file mode 100644 index 8833481..0000000 --- a/2.0/patches/08_all_mod_ssl-ssl-client-cert-post.patch +++ /dev/null @@ -1,332 +0,0 @@ ---- - modules/ssl/mod_ssl.h | 4 - modules/ssl/ssl_engine_io.c | 185 ++++++++++++++++++++++++++++++++++++++++ - modules/ssl/ssl_engine_kernel.c | 96 ++++++-------------- - 3 files changed, 218 insertions(+), 67 deletions(-) - ---- a/modules/ssl/mod_ssl.h -+++ b/modules/ssl/mod_ssl.h -@@ -682,6 +682,10 @@ void ssl_io_filter_init(conn_rec - void ssl_io_filter_register(apr_pool_t *); - long ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long); - -+/* ssl_io_buffer_fill fills the setaside buffering of the HTTP request -+ * to allow an SSL renegotiation to take place. */ -+int ssl_io_buffer_fill(request_rec *r); -+ - /* PRNG */ - int ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *); - ---- a/modules/ssl/ssl_engine_io.c -+++ b/modules/ssl/ssl_engine_io.c -@@ -880,6 +880,7 @@ static apr_status_t ssl_io_filter_error( - } - - static const char ssl_io_filter[] = "SSL/TLS Filter"; -+static const char ssl_io_buffer[] = "SSL/TLS Buffer"; - - /* - * Close the SSL part of the socket connection -@@ -1373,6 +1374,187 @@ static apr_status_t ssl_io_filter_output - return status; - } - -+/* 128K maximum buffer size by default. */ -+#ifndef SSL_MAX_IO_BUFFER -+#define SSL_MAX_IO_BUFFER (128 * 1024) -+#endif -+ -+struct modssl_buffer_ctx { -+ apr_bucket_brigade *bb; -+ apr_pool_t *pool; -+}; -+ -+int ssl_io_buffer_fill(request_rec *r) -+{ -+ conn_rec *c = r->connection; -+ struct modssl_buffer_ctx *ctx; -+ apr_bucket_brigade *tempb; -+ apr_off_t total = 0; /* total length buffered */ -+ int eos = 0; /* non-zero once EOS is seen */ -+ -+ /* Create the context which will be passed to the input filter; -+ * containing a setaside pool and a brigade which constrain the -+ * lifetime of the buffered data. */ -+ ctx = apr_palloc(r->pool, sizeof *ctx); -+ apr_pool_create(&ctx->pool, r->pool); -+ ctx->bb = apr_brigade_create(ctx->pool, c->bucket_alloc); -+ -+ /* ... and a temporary brigade. */ -+ tempb = apr_brigade_create(r->pool, c->bucket_alloc); -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "filling buffer"); -+ -+ do { -+ apr_status_t rv; -+ apr_bucket *e, *next; -+ -+ /* The request body is read from the protocol-level input -+ * filters; the buffering filter will reinject it from that -+ * level, allowing content/resource filters to run later, if -+ * necessary. */ -+ -+ rv = ap_get_brigade(r->proto_input_filters, tempb, AP_MODE_READBYTES, -+ APR_BLOCK_READ, 8192); -+ if (rv) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, -+ "could not read request body for SSL buffer"); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ -+ /* Iterate through the returned brigade: setaside each bucket -+ * into the context's pool and move it into the brigade. */ -+ for (e = APR_BRIGADE_FIRST(tempb); -+ e != APR_BRIGADE_SENTINEL(tempb) && !eos; e = next) { -+ const char *data; -+ apr_size_t len; -+ -+ next = APR_BUCKET_NEXT(e); -+ -+ if (APR_BUCKET_IS_EOS(e)) { -+ eos = 1; -+ } else if (!APR_BUCKET_IS_METADATA(e)) { -+ rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ); -+ if (rv != APR_SUCCESS) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, -+ "could not read bucket for SSL buffer"); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ total += len; -+ } -+ -+ rv = apr_bucket_setaside(e, ctx->pool); -+ if (rv != APR_SUCCESS) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, -+ "could not setaside bucket for SSL buffer"); -+ return HTTP_INTERNAL_SERVER_ERROR; -+ } -+ -+ APR_BUCKET_REMOVE(e); -+ APR_BRIGADE_INSERT_TAIL(ctx->bb, e); -+ } -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, -+ "total of %" APR_OFF_T_FMT " bytes in buffer, eos=%d", -+ total, eos); -+ -+ /* Fail if this exceeds the maximum buffer size. */ -+ if (total > SSL_MAX_IO_BUFFER) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "request body exceeds maximum size for SSL buffer"); -+ return HTTP_REQUEST_ENTITY_TOO_LARGE; -+ } -+ -+ } while (!eos); -+ -+ apr_brigade_destroy(tempb); -+ -+ /* Insert the filter which will supply the buffered data. */ -+ ap_add_input_filter(ssl_io_buffer, ctx, r, c); -+ -+ return 0; -+} -+ -+/* This input filter supplies the buffered request body to the caller -+ * from the brigade stored in f->ctx. */ -+static apr_status_t ssl_io_filter_buffer(ap_filter_t *f, -+ apr_bucket_brigade *bb, -+ ap_input_mode_t mode, -+ apr_read_type_e block, -+ apr_off_t bytes) -+{ -+ struct modssl_buffer_ctx *ctx = f->ctx; -+ apr_status_t rv; -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, -+ "read from buffered SSL brigade, mode %d, " -+ "%" APR_OFF_T_FMT " bytes", -+ mode, bytes); -+ -+ if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) { -+ return APR_ENOTIMPL; -+ } -+ -+ if (mode == AP_MODE_READBYTES) { -+ apr_bucket *e; -+ -+ /* Partition the buffered brigade. */ -+ rv = apr_brigade_partition(ctx->bb, bytes, &e); -+ if (rv && rv != APR_INCOMPLETE) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, -+ "could not partition buffered SSL brigade"); -+ ap_remove_input_filter(f); -+ return rv; -+ } -+ -+ /* If the buffered brigade contains less then the requested -+ * length, just pass it all back. */ -+ if (rv == APR_INCOMPLETE) { -+ APR_BRIGADE_CONCAT(bb, ctx->bb); -+ } else { -+ apr_bucket *d = APR_BRIGADE_FIRST(ctx->bb); -+ -+ e = APR_BUCKET_PREV(e); -+ -+ /* Unsplice the partitioned segment and move it into the -+ * passed-in brigade; no convenient way to do this with -+ * the APR_BRIGADE_* macros. */ -+ APR_RING_UNSPLICE(d, e, link); -+ APR_RING_SPLICE_HEAD(&bb->list, d, e, apr_bucket, link); -+ -+ APR_BRIGADE_CHECK_CONSISTENCY(bb); -+ APR_BRIGADE_CHECK_CONSISTENCY(ctx->bb); -+ } -+ } -+ else { -+ /* Split a line into the passed-in brigade. */ -+ rv = apr_brigade_split_line(bb, ctx->bb, mode, bytes); -+ -+ if (rv) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, -+ "could not split line from buffered SSL brigade"); -+ ap_remove_input_filter(f); -+ return rv; -+ } -+ } -+ -+ if (APR_BRIGADE_EMPTY(ctx->bb)) { -+ apr_bucket *e = APR_BRIGADE_LAST(bb); -+ -+ /* Ensure that the brigade is terminated by an EOS if the -+ * buffered request body has been entirely consumed. */ -+ if (e == APR_BRIGADE_SENTINEL(bb) || !APR_BUCKET_IS_EOS(e)) { -+ e = apr_bucket_eos_create(f->c->bucket_alloc); -+ APR_BRIGADE_INSERT_TAIL(bb, e); -+ } -+ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, -+ "buffered SSL brigade now exhausted; removing filter"); -+ ap_remove_input_filter(f); -+ } -+ -+ return APR_SUCCESS; -+} -+ - static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c, - SSL *ssl) - { -@@ -1430,6 +1612,9 @@ void ssl_io_filter_register(apr_pool_t * - { - ap_register_input_filter (ssl_io_filter, ssl_io_filter_input, NULL, AP_FTYPE_CONNECTION + 5); - ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5); -+ -+ ap_register_input_filter (ssl_io_buffer, ssl_io_filter_buffer, NULL, AP_FTYPE_PROTOCOL - 1); -+ - return; - } - ---- a/modules/ssl/ssl_engine_kernel.c -+++ b/modules/ssl/ssl_engine_kernel.c -@@ -483,73 +483,35 @@ int ssl_hook_Access(request_rec *r) - } - #endif /* HAVE_SSL_SET_CERT_STORE */ - -- /* -- * SSL renegotiations in conjunction with HTTP -- * requests using the POST method are not supported. -- * -- * Background: -- * -- * 1. When the client sends a HTTP/HTTPS request, Apache's core code -- * reads only the request line ("METHOD /path HTTP/x.y") and the -- * attached MIME headers ("Foo: bar") up to the terminating line ("CR -- * LF"). An attached request body (for instance the data of a POST -- * method) is _NOT_ read. Instead it is read by mod_cgi's content -- * handler and directly passed to the CGI script. -- * -- * 2. mod_ssl supports per-directory re-configuration of SSL parameters. -- * This is implemented by performing an SSL renegotiation of the -- * re-configured parameters after the request is read, but before the -- * response is sent. In more detail: the renegotiation happens after the -- * request line and MIME headers were read, but _before_ the attached -- * request body is read. The reason simply is that in the HTTP protocol -- * usually there is no acknowledgment step between the headers and the -- * body (there is the 100-continue feature and the chunking facility -- * only), so Apache has no API hook for this step. -- * -- * 3. the problem now occurs when the client sends a POST request for -- * URL /foo via HTTPS the server and the server has SSL parameters -- * re-configured on a per-URL basis for /foo. Then mod_ssl has to -- * perform an SSL renegotiation after the request was read and before -- * the response is sent. But the problem is the pending POST body data -- * in the receive buffer of SSL (which Apache still has not read - it's -- * pending until mod_cgi sucks it in). When mod_ssl now tries to perform -- * the renegotiation the pending data leads to an I/O error. -- * -- * Solution Idea: -- * -- * There are only two solutions: Either to simply state that POST -- * requests to URLs with SSL re-configurations are not allowed, or to -- * renegotiate really after the _complete_ request (i.e. including -- * the POST body) was read. Obviously the latter would be preferred, -- * but it cannot be done easily inside Apache, because as already -- * mentioned, there is no API step between the body reading and the body -- * processing. And even when we mod_ssl would hook directly into the -- * loop of mod_cgi, we wouldn't solve the problem for other handlers, of -- * course. So the only general solution is to suck in the pending data -- * of the request body from the OpenSSL BIO into the Apache BUFF. Then -- * the renegotiation can be done and after this step Apache can proceed -- * processing the request as before. -- * -- * Solution Implementation: -- * -- * We cannot simply suck in the data via an SSL_read-based loop because of -- * HTTP chunking. Instead we _have_ to use the Apache API for this step which -- * is aware of HTTP chunking. So the trick is to suck in the pending request -- * data via the Apache API (which uses Apache's BUFF code and in the -- * background mod_ssl's I/O glue code) and re-inject it later into the Apache -- * BUFF code again. This way the data flows twice through the Apache BUFF, of -- * course. But this way the solution doesn't depend on any Apache specifics -- * and is fully transparent to Apache modules. -- * -- * !! BUT ALL THIS IS STILL NOT RE-IMPLEMENTED FOR APACHE 2.0 !! -- */ -- if (renegotiate && !renegotiate_quick && (r->method_number == M_POST)) { -- ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, -- "SSL Re-negotiation in conjunction " -- "with POST method not supported! " -- "hint: try SSLOptions +OptRenegotiate"); -- -- return HTTP_METHOD_NOT_ALLOWED; -+ /* If a renegotiation is now required for this location, and the -+ * request includes a message body (and the client has not -+ * requested a "100 Continue" response), then the client will be -+ * streaming the request body over the wire already. In that -+ * case, it is not possible to stop and perform a new SSL -+ * handshake immediately; once the SSL library moves to the -+ * "accept" state, it will reject the SSL packets which the client -+ * is sending for the request body. -+ * -+ * To allow authentication to complete in this auth hook, the -+ * solution used here is to fill a (bounded) buffer with the -+ * request body, and then to reinject that request body later. -+ */ -+ if (renegotiate && !renegotiate_quick -+ && (apr_table_get(r->headers_in, "transfer-encoding") -+ || (apr_table_get(r->headers_in, "content-length") -+ && strcmp(apr_table_get(r->headers_in, "content-length"), "0"))) -+ && !r->expecting_100) { -+ int rv; -+ -+ /* Fill the I/O buffer with the request body if possible. */ -+ rv = ssl_io_buffer_fill(r); -+ -+ if (rv) { -+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, -+ "could not buffer message body to allow " -+ "SSL renegotiation to proceed"); -+ return rv; -+ } - } - - /* diff --git a/2.0/patches/80_all_CVE-2007-5752.patch b/2.0/patches/80_all_CVE-2007-5752.patch deleted file mode 100644 index cc2c057..0000000 --- a/2.0/patches/80_all_CVE-2007-5752.patch +++ /dev/null @@ -1,42 +0,0 @@ -Index: modules/generators/mod_status.c -=================================================================== ---- modules/generators/mod_status.c (revision 555481) -+++ modules/generators/mod_status.c (revision 555482) -@@ -269,7 +269,7 @@ - if (r->method_number != M_GET) - return DECLINED; - -- ap_set_content_type(r, "text/html"); -+ ap_set_content_type(r, "text/html; charset=ISO-8859-1"); - - /* - * Simple table-driven form data set parser that lets you alter the header -@@ -298,7 +298,7 @@ - no_table_report = 1; - break; - case STAT_OPT_AUTO: -- ap_set_content_type(r, "text/plain"); -+ ap_set_content_type(r, "text/plain; charset=ISO-8859-1"); - short_report = 1; - break; - } -@@ -664,7 +664,8 @@ - ap_escape_html(r->pool, - ws_record->client), - ap_escape_html(r->pool, -- ws_record->request), -+ ap_escape_logitem(r->pool, -+ ws_record->request)), - ap_escape_html(r->pool, - ws_record->vhost)); - } -@@ -753,7 +754,8 @@ - ap_escape_html(r->pool, - ws_record->vhost), - ap_escape_html(r->pool, -- ws_record->request)); -+ ap_escape_logitem(r->pool, -+ ws_record->request))); - } /* no_table_report */ - } /* for (j...) */ - } /* for (i...) */ diff --git a/2.0/patches/81_all_CVE-2007-3304.patch b/2.0/patches/81_all_CVE-2007-3304.patch deleted file mode 100644 index 7e70654..0000000 --- a/2.0/patches/81_all_CVE-2007-3304.patch +++ /dev/null @@ -1,16 +0,0 @@ -Index: server/mpm_common.c -=================================================================== ---- server/mpm_common.c (revision 556297) -+++ server/mpm_common.c (revision 556298) -@@ -110,6 +110,11 @@ - apr_proc_t proc; - apr_status_t waitret; - -+ /* Ensure pid sanity. */ -+ if (pid < 1) { -+ return 1; -+ } -+ - proc.pid = pid; - waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT); - if (waitret != APR_CHILD_NOTDONE) { diff --git a/2.0/patches/82_all_CVE-2007-1863.patch b/2.0/patches/82_all_CVE-2007-1863.patch deleted file mode 100644 index af5b458..0000000 --- a/2.0/patches/82_all_CVE-2007-1863.patch +++ /dev/null @@ -1,75 +0,0 @@ -Index: modules/experimental/cache_util.c -=================================================================== ---- modules/experimental/cache_util.c (revision 556618) -+++ modules/experimental/cache_util.c (revision 556619) -@@ -186,7 +186,8 @@ - age = ap_cache_current_age(info, age_c, r->request_time); - - /* extract s-maxage */ -- if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val)) { -+ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val) -+ && val != NULL) { - smaxage = apr_atoi64(val); - } - else if (cc_ceresp && ap_cache_liststr(r->pool, cc_ceresp, "s-maxage", &val)) { -@@ -197,7 +198,8 @@ - } - - /* extract max-age from request */ -- if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val)) { -+ if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val) -+ && val != NULL) { - maxage_req = apr_atoi64(val); - } - else { -@@ -205,7 +207,8 @@ - } - - /* extract max-age from response */ -- if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val)) { -+ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val) -+ && val != NULL) { - maxage_cresp = apr_atoi64(val); - } - else if (cc_ceresp && ap_cache_liststr(r->pool, cc_ceresp, "max-age", &val)) { -@@ -231,14 +234,28 @@ - - /* extract max-stale */ - if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-stale", &val)) { -- maxstale = apr_atoi64(val); -+ if(val != NULL) { -+ maxstale = apr_atoi64(val); -+ } -+ else { -+ /* -+ * If no value is assigned to max-stale, then the client is willing -+ * to accept a stale response of any age (RFC2616 14.9.3). We will -+ * set it to one year in this case as this situation is somewhat -+ * similar to a "never expires" Expires header (RFC2616 14.21) -+ * which is set to a date one year from the time the response is -+ * sent in this case. -+ */ -+ maxstale = APR_INT64_C(86400*365); -+ } - } - else { - maxstale = 0; - } - - /* extract min-fresh */ -- if (cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val)) { -+ if (cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val) -+ && val != NULL) { - minfresh = apr_atoi64(val); - } - else { -@@ -384,6 +401,9 @@ - next - val_start); - } - } -+ else { -+ *val = NULL; -+ } - } - return 1; - } diff --git a/2.0/patches/83_all_CVE-2007-2874.patch b/2.0/patches/83_all_CVE-2007-2874.patch deleted file mode 100644 index 0c63c1f..0000000 --- a/2.0/patches/83_all_CVE-2007-2874.patch +++ /dev/null @@ -1,88 +0,0 @@ -Index: modules/proxy/proxy_util.c -=================================================================== ---- modules/proxy/proxy_util.c (revision 563328) -+++ modules/proxy/proxy_util.c (revision 563329) -@@ -259,70 +259,28 @@ - return NULL; - } - --static const char * const lwday[7] = --{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; -- - /* - * If the date is a valid RFC 850 date or asctime() date, then it -- * is converted to the RFC 1123 format, otherwise it is not modified. -- * This routine is not very fast at doing conversions, as it uses -- * sscanf and sprintf. However, if the date is already correctly -- * formatted, then it exits very quickly. -+ * is converted to the RFC 1123 format. - */ - PROXY_DECLARE(const char *) -- ap_proxy_date_canon(apr_pool_t *p, const char *x1) -+ ap_proxy_date_canon(apr_pool_t *p, const char *date) - { -- char *x = apr_pstrdup(p, x1); -- int wk, mday, year, hour, min, sec, mon; -- char *q, month[4], zone[4], week[4]; -+ apr_status_t rv; -+ char* ndate; - -- q = strchr(x, ','); -- /* check for RFC 850 date */ -- if (q != NULL && q - x > 3 && q[1] == ' ') { -- *q = '\0'; -- for (wk = 0; wk < 7; wk++) -- if (strcmp(x, lwday[wk]) == 0) -- break; -- *q = ','; -- if (wk == 7) -- return x; /* not a valid date */ -- if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' || -- q[17] != ':' || strcmp(&q[20], " GMT") != 0) -- return x; -- if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year, -- &hour, &min, &sec, zone) != 7) -- return x; -- if (year < 70) -- year += 2000; -- else -- year += 1900; -+ apr_time_t time = apr_date_parse_http(date); -+ if (!time) { -+ return date; - } -- else { --/* check for acstime() date */ -- if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' || -- x[16] != ':' || x[19] != ' ' || x[24] != '\0') -- return x; -- if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour, -- &min, &sec, &year) != 7) -- return x; -- for (wk = 0; wk < 7; wk++) -- if (strcmp(week, apr_day_snames[wk]) == 0) -- break; -- if (wk == 7) -- return x; -+ -+ ndate = apr_palloc(p, APR_RFC822_DATE_LEN); -+ rv = apr_rfc822_date(ndate, time); -+ if (rv != APR_SUCCESS) { -+ return date; - } - --/* check date */ -- for (mon = 0; mon < 12; mon++) -- if (strcmp(month, apr_month_snames[mon]) == 0) -- break; -- if (mon == 12) -- return x; -- -- q = apr_palloc(p, 30); -- apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", apr_day_snames[wk], -- mday, apr_month_snames[mon], year, hour, min, sec); -- return q; -+ return ndate; - } - - PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r) diff --git a/2.2/conf/apache2-builtin-mods b/2.2/conf/apache2-builtin-mods index ca90c6a..a0174bd 100644 --- a/2.2/conf/apache2-builtin-mods +++ b/2.2/conf/apache2-builtin-mods @@ -42,8 +42,8 @@ mod_authz_user shared mod_autoindex shared mod_cache shared mod_cern_meta disabled -mod_cgi shared -mod_cgid shared +#mod_cgi disabled # enable via USE-flag +#mod_cgid disabled # enable via USE-flag mod_charset_lite disabled mod_dav shared mod_dav_fs shared diff --git a/2.2/patches/04_all_mod_dbd_r553563.patch b/2.2/patches/04_all_mod_dbd_r553563.patch deleted file mode 100644 index 51dd29b..0000000 --- a/2.2/patches/04_all_mod_dbd_r553563.patch +++ /dev/null @@ -1,1279 +0,0 @@ -diff -NurpP httpd-2.2.4.orig/modules/database/mod_dbd.c httpd-2.2.4/modules/database/mod_dbd.c ---- httpd-2.2.4.orig/modules/database/mod_dbd.c 2006-12-12 15:17:17.000000000 +0100 -+++ httpd-2.2.4/modules/database/mod_dbd.c 2007-08-19 15:47:47.822568162 +0200 -@@ -20,15 +20,21 @@ - * http://apache.webthing.com/database/ - */ - --#include <ctype.h> -+#include "apr_reslist.h" -+#include "apr_strings.h" -+#include "apr_hash.h" -+#include "apr_tables.h" -+#include "apr_lib.h" -+#include "apr_dbd.h" -+ -+#define APR_WANT_MEMFUNC -+#define APR_WANT_STRFUNC -+#include "apr_want.h" - - #include "http_protocol.h" - #include "http_config.h" - #include "http_log.h" - #include "http_request.h" --#include "apr_reslist.h" --#include "apr_strings.h" --#include "apr_dbd.h" - #include "mod_dbd.h" - - extern module AP_MODULE_DECLARE_DATA dbd_module; -@@ -40,126 +46,199 @@ extern module AP_MODULE_DECLARE_DATA dbd - #define NMAX_SET 0x4 - #define EXPTIME_SET 0x8 - --typedef struct dbd_prepared { -- const char *label; -- const char *query; -- struct dbd_prepared *next; --} dbd_prepared; --typedef struct svr_cfg { -+typedef struct { -+ server_rec *server; - const char *name; - const char *params; - int persist; -- dbd_prepared *prepared; - #if APR_HAS_THREADS -- apr_thread_mutex_t *mutex; -- apr_pool_t *pool; -- apr_reslist_t *dbpool; - int nmin; - int nkeep; - int nmax; - int exptime; -+ int set; -+#endif -+ apr_hash_t *queries; -+} dbd_cfg_t; -+ -+typedef struct dbd_group_t dbd_group_t; -+ -+struct dbd_group_t { -+ dbd_cfg_t *cfg; -+ dbd_group_t *next; -+ apr_pool_t *pool; -+#if APR_HAS_THREADS -+ apr_thread_mutex_t *mutex; -+ apr_reslist_t *reslist; -+ int destroyed; - #else -- ap_dbd_t *conn; -+ ap_dbd_t *rec; - #endif -- unsigned int set; -+}; -+ -+typedef struct { -+ dbd_cfg_t *cfg; -+ dbd_group_t *group; - } svr_cfg; - - typedef enum { cmd_name, cmd_params, cmd_persist, - cmd_min, cmd_keep, cmd_max, cmd_exp - } cmd_parts; - --static apr_hash_t *dbd_prepared_defns; -+static apr_pool_t *config_pool; -+static dbd_group_t *group_list; - - /* a default DBDriver value that'll generate meaningful error messages */ - static const char *const no_dbdriver = "[DBDriver unset]"; - --#define ISINT(val) \ -- for (p = val; *p; ++p) \ -- if (!isdigit(*p)) \ -- return "Argument must be numeric!" --static const char *dbd_param(cmd_parms *cmd, void *cfg, const char *val) -+/* A default nmin of >0 will help with generating meaningful -+ * startup error messages if the database is down. -+ */ -+#define DEFAULT_NMIN 1 -+#define DEFAULT_NKEEP 2 -+#define DEFAULT_NMAX 10 -+#define DEFAULT_EXPTIME 300 -+ -+static void *create_dbd_config(apr_pool_t *pool, server_rec *s) -+{ -+ svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg)); -+ dbd_cfg_t *cfg = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t)); -+ -+ cfg->server = s; -+ cfg->name = no_dbdriver; /* to generate meaningful error messages */ -+ cfg->params = ""; /* don't risk segfault on misconfiguration */ -+ cfg->persist = -1; -+#if APR_HAS_THREADS -+ cfg->nmin = DEFAULT_NMIN; -+ cfg->nkeep = DEFAULT_NKEEP; -+ cfg->nmax = DEFAULT_NMAX; -+ cfg->exptime = DEFAULT_EXPTIME; -+#endif -+ cfg->queries = apr_hash_make(pool); -+ -+ return svr; -+} -+ -+static void *merge_dbd_config(apr_pool_t *pool, void *basev, void *addv) -+{ -+ dbd_cfg_t *base = ((svr_cfg*) basev)->cfg; -+ dbd_cfg_t *add = ((svr_cfg*) addv)->cfg; -+ svr_cfg *svr = apr_pcalloc(pool, sizeof(svr_cfg)); -+ dbd_cfg_t *new = svr->cfg = apr_pcalloc(pool, sizeof(dbd_cfg_t)); -+ -+ new->server = add->server; -+ new->name = (add->name != no_dbdriver) ? add->name : base->name; -+ new->params = strcmp(add->params, "") ? add->params : base->params; -+ new->persist = (add->persist != -1) ? add->persist : base->persist; -+#if APR_HAS_THREADS -+ new->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin; -+ new->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep; -+ new->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax; -+ new->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime; -+#endif -+ new->queries = apr_hash_overlay(pool, add->queries, base->queries); -+ -+ return svr; -+} -+ -+#define ISINT(val) do { \ -+ const char *p; \ -+ \ -+ for (p = val; *p; ++p) { \ -+ if (!apr_isdigit(*p)) { \ -+ return "Argument must be numeric!"; \ -+ } \ -+ } \ -+ } while (0) -+ -+static const char *dbd_param(cmd_parms *cmd, void *dconf, const char *val) - { -- const char *p; - const apr_dbd_driver_t *driver = NULL; -- svr_cfg *svr = (svr_cfg*) ap_get_module_config -- (cmd->server->module_config, &dbd_module); -+ svr_cfg *svr = ap_get_module_config(cmd->server->module_config, -+ &dbd_module); -+ dbd_cfg_t *cfg = svr->cfg; - - switch ((long) cmd->info) { - case cmd_name: -- svr->name = val; -+ cfg->name = val; - /* loading the driver involves once-only dlloading that is - * best done at server startup. This also guarantees that - * we won't return an error later. - */ -- switch (apr_dbd_get_driver(cmd->pool, svr->name, &driver)) { -+ switch (apr_dbd_get_driver(cmd->pool, cfg->name, &driver)) { - case APR_ENOTIMPL: -- return apr_psprintf(cmd->pool, "DBD: No driver for %s", svr->name); -+ return apr_psprintf(cmd->pool, "DBD: No driver for %s", cfg->name); - case APR_EDSOOPEN: - return apr_psprintf(cmd->pool, -+#ifdef NETWARE -+ "DBD: Can't load driver file dbd%s.nlm", -+#else - "DBD: Can't load driver file apr_dbd_%s.so", -- svr->name); -+#endif -+ cfg->name); - case APR_ESYMNOTFOUND: - return apr_psprintf(cmd->pool, - "DBD: Failed to load driver apr_dbd_%s_driver", -- svr->name); -+ cfg->name); - } - break; - case cmd_params: -- svr->params = val; -+ cfg->params = val; - break; - #if APR_HAS_THREADS - case cmd_min: - ISINT(val); -- svr->nmin = atoi(val); -- svr->set |= NMIN_SET; -+ cfg->nmin = atoi(val); -+ cfg->set |= NMIN_SET; - break; - case cmd_keep: - ISINT(val); -- svr->nkeep = atoi(val); -- svr->set |= NKEEP_SET; -+ cfg->nkeep = atoi(val); -+ cfg->set |= NKEEP_SET; - break; - case cmd_max: - ISINT(val); -- svr->nmax = atoi(val); -- svr->set |= NMAX_SET; -+ cfg->nmax = atoi(val); -+ cfg->set |= NMAX_SET; - break; - case cmd_exp: - ISINT(val); -- svr->exptime = atoi(val); -- svr->set |= EXPTIME_SET; -+ cfg->exptime = atoi(val); -+ cfg->set |= EXPTIME_SET; - break; - #endif - } -+ - return NULL; - } --static const char *dbd_param_flag(cmd_parms *cmd, void *cfg, int flag) -+ -+static const char *dbd_param_flag(cmd_parms *cmd, void *dconf, int flag) - { -- svr_cfg *svr = (svr_cfg*) ap_get_module_config -- (cmd->server->module_config, &dbd_module); -+ svr_cfg *svr = ap_get_module_config(cmd->server->module_config, -+ &dbd_module); - - switch ((long) cmd->info) { - case cmd_persist: -- svr->persist = flag; -+ svr->cfg->persist = flag; - break; - } -+ - return NULL; - } --DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query, -- const char *label) --{ -- dbd_prepared *prepared = apr_pcalloc(s->process->pool, sizeof(dbd_prepared)); -- const char *key = apr_psprintf(s->process->pool, "%pp", s); -- prepared->label = label; -- prepared->query = query; -- prepared->next = apr_hash_get(dbd_prepared_defns, key, APR_HASH_KEY_STRING); -- apr_hash_set(dbd_prepared_defns, key, APR_HASH_KEY_STRING, prepared); --} --static const char *dbd_prepare(cmd_parms *cmd, void *cfg, const char *query, -+ -+static const char *dbd_prepare(cmd_parms *cmd, void *dconf, const char *query, - const char *label) - { -+ if (!label) { -+ label = query; -+ query = ""; -+ } -+ - ap_dbd_prepare(cmd->server, query, label); -+ - return NULL; - } -+ - static const command_rec dbd_cmds[] = { - AP_INIT_TAKE1("DBDriver", dbd_param, (void*)cmd_name, RSRC_CONF, - "SQL Driver"), -@@ -167,8 +246,9 @@ static const command_rec dbd_cmds[] = { - "SQL Driver Params"), - AP_INIT_FLAG("DBDPersist", dbd_param_flag, (void*)cmd_persist, RSRC_CONF, - "Use persistent connection/pool"), -- AP_INIT_TAKE2("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF, -- "Prepared SQL statement, label"), -+ AP_INIT_TAKE12("DBDPrepareSQL", dbd_prepare, NULL, RSRC_CONF, -+ "SQL statement to prepare (or nothing, to override " -+ "statement inherited from main server) and label"), - #if APR_HAS_THREADS - AP_INIT_TAKE1("DBDMin", dbd_param, (void*)cmd_min, RSRC_CONF, - "Minimum number of connections"), -@@ -183,370 +263,545 @@ static const command_rec dbd_cmds[] = { - #endif - {NULL} - }; --static void *dbd_merge(apr_pool_t *pool, void *BASE, void *ADD) { -- svr_cfg *base = (svr_cfg*) BASE; -- svr_cfg *add = (svr_cfg*) ADD; -- svr_cfg *cfg = apr_pcalloc(pool, sizeof(svr_cfg)); -- cfg->name = (add->name != no_dbdriver) ? add->name : base->name; -- cfg->params = strcmp(add->params, "") ? add->params : base->params; -- cfg->persist = (add->persist == -1) ? base->persist : add->persist; --#if APR_HAS_THREADS -- cfg->nmin = (add->set&NMIN_SET) ? add->nmin : base->nmin; -- cfg->nkeep = (add->set&NKEEP_SET) ? add->nkeep : base->nkeep; -- cfg->nmax = (add->set&NMAX_SET) ? add->nmax : base->nmax; -- cfg->exptime = (add->set&EXPTIME_SET) ? add->exptime : base->exptime; --#endif -- cfg->set = add->set | base->set; -- cfg->prepared = (add->prepared != NULL) ? add->prepared : base->prepared; -- return (void*) cfg; -+ -+static int dbd_pre_config(apr_pool_t *pconf, apr_pool_t *plog, -+ apr_pool_t *ptemp) -+{ -+ config_pool = pconf; -+ group_list = NULL; -+ return OK; - } --/* A default nmin of >0 will help with generating meaningful -- * startup error messages if the database is down. -- */ --#define DEFAULT_NMIN 1 --#define DEFAULT_NKEEP 2 --#define DEFAULT_NMAX 10 --#define DEFAULT_EXPTIME 300 --static void *dbd_cfg(apr_pool_t *p, server_rec *x) -+ -+DBD_DECLARE_NONSTD(void) ap_dbd_prepare(server_rec *s, const char *query, -+ const char *label) -+{ -+ svr_cfg *svr; -+ -+ svr = ap_get_module_config(s->module_config, &dbd_module); -+ if (!svr) { -+ /* some modules may call from within config directive handlers, and -+ * if these are called in a server context that contains no mod_dbd -+ * config directives, then we have to create our own server config -+ */ -+ svr = create_dbd_config(config_pool, s); -+ ap_set_module_config(s->module_config, &dbd_module, svr); -+ } -+ -+ if (apr_hash_get(svr->cfg->queries, label, APR_HASH_KEY_STRING) -+ && strcmp(query, "")) { -+ ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, -+ "conflicting SQL statements with label %s", label); -+ } -+ -+ apr_hash_set(svr->cfg->queries, label, APR_HASH_KEY_STRING, query); -+} -+ -+typedef struct { -+ const char *label, *query; -+} dbd_query_t; -+ -+static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog, -+ apr_pool_t *ptemp, server_rec *s) - { -- svr_cfg *svr = (svr_cfg*) apr_pcalloc(p, sizeof(svr_cfg)); -- svr->params = ""; /* don't risk segfault on misconfiguration */ -- svr->name = no_dbdriver; /* to generate meaningful error messages */ -- svr->persist = -1; --#if APR_HAS_THREADS -- svr->nmin = DEFAULT_NMIN; -- svr->nkeep = DEFAULT_NKEEP; -- svr->nmax = DEFAULT_NMAX; -- svr->exptime = DEFAULT_EXPTIME; -+ server_rec *sp; -+ apr_array_header_t *add_queries = apr_array_make(ptemp, 10, -+ sizeof(dbd_query_t)); -+ -+ for (sp = s; sp; sp = sp->next) { -+ svr_cfg *svr = ap_get_module_config(sp->module_config, &dbd_module); -+ dbd_cfg_t *cfg = svr->cfg; -+ apr_hash_index_t *hi_first = apr_hash_first(ptemp, cfg->queries); -+ dbd_group_t *group; -+ -+ /* dbd_setup in 2.2.3 and under was causing spurious error messages -+ * when dbd isn't configured. We can stop that with a quick check here -+ * together with a similar check in ap_dbd_open (where being -+ * unconfigured is a genuine error that must be reported). -+ */ -+ if (cfg->name == no_dbdriver || !cfg->persist) { -+ continue; -+ } -+ -+ for (group = group_list; group; group = group->next) { -+ dbd_cfg_t *group_cfg = group->cfg; -+ apr_hash_index_t *hi; -+ int group_ok = 1; -+ -+ if (strcmp(cfg->name, group_cfg->name) -+ || strcmp(cfg->params, group_cfg->params)) { -+ continue; -+ } -+ -+#if APR_HAS_THREADS -+ if (cfg->nmin != group_cfg->nmin -+ || cfg->nkeep != group_cfg->nkeep -+ || cfg->nmax != group_cfg->nmax -+ || cfg->exptime != group_cfg->exptime) { -+ continue; -+ } - #endif -- return svr; -+ -+ add_queries->nelts = 0; -+ -+ for (hi = hi_first; hi; hi = apr_hash_next(hi)) { -+ const char *label, *query; -+ const char *group_query; -+ -+ apr_hash_this(hi, (void*) &label, NULL, (void*) &query); -+ -+ group_query = apr_hash_get(group_cfg->queries, label, -+ APR_HASH_KEY_STRING); -+ -+ if (!group_query) { -+ dbd_query_t *add_query = apr_array_push(add_queries); -+ -+ add_query->label = label; -+ add_query->query = query; -+ } -+ else if (strcmp(query, group_query)) { -+ group_ok = 0; -+ break; -+ } -+ } -+ -+ if (group_ok) { -+ int i; -+ -+ for (i = 0; i < add_queries->nelts; ++i) { -+ dbd_query_t *add_query = ((dbd_query_t*) add_queries->elts) -+ + i; -+ -+ apr_hash_set(group_cfg->queries, add_query->label, -+ APR_HASH_KEY_STRING, add_query->query); -+ } -+ -+ svr->group = group; -+ break; -+ } -+ } -+ -+ if (!svr->group) { -+ svr->group = group = apr_pcalloc(pconf, sizeof(dbd_group_t)); -+ -+ group->cfg = cfg; -+ -+ group->next = group_list; -+ group_list = group; -+ } -+ } -+ -+ return OK; - } --static apr_status_t dbd_prepared_init(apr_pool_t *pool, svr_cfg *svr, -- ap_dbd_t *dbd) -+ -+static apr_status_t dbd_prepared_init(apr_pool_t *pool, dbd_cfg_t *cfg, -+ ap_dbd_t *rec) - { -- dbd_prepared *p; -- apr_status_t ret = APR_SUCCESS; -- apr_dbd_prepared_t *stmt; -- dbd->prepared = apr_hash_make(pool); -+ apr_hash_index_t *hi; -+ apr_status_t rv = APR_SUCCESS; -+ -+ rec->prepared = apr_hash_make(pool); -+ -+ for (hi = apr_hash_first(pool, cfg->queries); hi; -+ hi = apr_hash_next(hi)) { -+ const char *label, *query; -+ apr_dbd_prepared_t *stmt; -+ -+ apr_hash_this(hi, (void*) &label, NULL, (void*) &query); -+ -+ if (!strcmp(query, "")) { -+ continue; -+ } - -- for (p = svr->prepared; p; p = p->next) { - stmt = NULL; -- if (apr_dbd_prepare(dbd->driver, pool, dbd->handle, p->query, -- p->label, &stmt) == 0) { -- apr_hash_set(dbd->prepared, p->label, APR_HASH_KEY_STRING, stmt); -+ if (apr_dbd_prepare(rec->driver, pool, rec->handle, query, -+ label, &stmt)) { -+ rv = APR_EGENERAL; - } - else { -- ret = APR_EGENERAL; -+ apr_hash_set(rec->prepared, label, APR_HASH_KEY_STRING, stmt); - } - } -- return ret; -+ -+ return rv; - } --/************ svr cfg: manage db connection pool ****************/ -+ -+static apr_status_t dbd_close(void *data) -+{ -+ ap_dbd_t *rec = data; -+ -+ return apr_dbd_close(rec->driver, rec->handle); -+} -+ -+#if APR_HAS_THREADS -+static apr_status_t dbd_destruct(void *data, void *params, apr_pool_t *pool) -+{ -+ dbd_group_t *group = params; -+ -+ if (!group->destroyed) { -+ ap_dbd_t *rec = data; -+ -+ apr_pool_destroy(rec->pool); -+ } -+ -+ return APR_SUCCESS; -+} -+#endif -+ - /* an apr_reslist_constructor for SQL connections - * Also use this for opening in non-reslist modes, since it gives - * us all the error-handling in one place. - */ --static apr_status_t dbd_construct(void **db, void *params, apr_pool_t *pool) -+static apr_status_t dbd_construct(void **data_ptr, -+ void *params, apr_pool_t *pool) - { -- svr_cfg *svr = (svr_cfg*) params; -- ap_dbd_t *rec = apr_pcalloc(pool, sizeof(ap_dbd_t)); -+ dbd_group_t *group = params; -+ dbd_cfg_t *cfg = group->cfg; -+ apr_pool_t *rec_pool, *prepared_pool; -+ ap_dbd_t *rec; - apr_status_t rv; - -- /* this pool is mostly so dbd_close can destroy the prepared stmts */ -- rv = apr_pool_create(&rec->pool, pool); -+ rv = apr_pool_create(&rec_pool, pool); - if (rv != APR_SUCCESS) { -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool, -- "DBD: Failed to create memory pool"); -+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server, -+ "DBD: Failed to create memory pool"); -+ return rv; - } - --/* The driver is loaded at config time now, so this just checks a hash. -- * If that changes, the driver DSO could be registered to unload against -- * our pool, which is probably not what we want. Error checking isn't -- * necessary now, but in case that changes in the future ... -- */ -- rv = apr_dbd_get_driver(rec->pool, svr->name, &rec->driver); -- switch (rv) { -- case APR_ENOTIMPL: -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool, -- "DBD: driver for %s not available", svr->name); -- return rv; -- case APR_EDSOOPEN: -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool, -- "DBD: can't find driver for %s", svr->name); -- return rv; -- case APR_ESYMNOTFOUND: -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool, -- "DBD: driver for %s is invalid or corrupted", svr->name); -- return rv; -- default: -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool, -- "DBD: mod_dbd not compatible with apr in get_driver"); -+ rec = apr_pcalloc(rec_pool, sizeof(ap_dbd_t)); -+ -+ rec->pool = rec_pool; -+ -+ /* The driver is loaded at config time now, so this just checks a hash. -+ * If that changes, the driver DSO could be registered to unload against -+ * our pool, which is probably not what we want. Error checking isn't -+ * necessary now, but in case that changes in the future ... -+ */ -+ rv = apr_dbd_get_driver(rec->pool, cfg->name, &rec->driver); -+ if (rv != APR_SUCCESS) { -+ switch (rv) { -+ case APR_ENOTIMPL: -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, -+ "DBD: driver for %s not available", cfg->name); -+ break; -+ case APR_EDSOOPEN: -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, -+ "DBD: can't find driver for %s", cfg->name); -+ break; -+ case APR_ESYMNOTFOUND: -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, -+ "DBD: driver for %s is invalid or corrupted", -+ cfg->name); -+ break; -+ default: -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, -+ "DBD: mod_dbd not compatible with APR in get_driver"); -+ break; -+ } -+ -+ apr_pool_destroy(rec->pool); - return rv; -- case APR_SUCCESS: -- break; - } - -- rv = apr_dbd_open(rec->driver, rec->pool, svr->params, &rec->handle); -- switch (rv) { -- case APR_EGENERAL: -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool, -- "DBD: Can't connect to %s", svr->name); -+ rv = apr_dbd_open(rec->driver, rec->pool, cfg->params, &rec->handle); -+ if (rv != APR_SUCCESS) { -+ switch (rv) { -+ case APR_EGENERAL: -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, -+ "DBD: Can't connect to %s", cfg->name); -+ break; -+ default: -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, -+ "DBD: mod_dbd not compatible with APR in open"); -+ break; -+ } -+ -+ apr_pool_destroy(rec->pool); - return rv; -- default: -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool, -- "DBD: mod_dbd not compatible with apr in open"); -+ } -+ -+ apr_pool_cleanup_register(rec->pool, rec, dbd_close, -+ apr_pool_cleanup_null); -+ -+ /* we use a sub-pool for the prepared statements for each connection so -+ * that they will be cleaned up first, before the connection is closed -+ */ -+ rv = apr_pool_create(&prepared_pool, rec->pool); -+ if (rv != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->server, -+ "DBD: Failed to create memory pool"); -+ -+ apr_pool_destroy(rec->pool); - return rv; -- case APR_SUCCESS: -- break; - } -- *db = rec; -- rv = dbd_prepared_init(rec->pool, svr, rec); -+ -+ rv = dbd_prepared_init(prepared_pool, cfg, rec); - if (rv != APR_SUCCESS) { - const char *errmsg = apr_dbd_error(rec->driver, rec->handle, rv); -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, rec->pool, -- "DBD: failed to initialise prepared SQL statements: %s", -- (errmsg ? errmsg : "[???]")); -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->server, -+ "DBD: failed to prepare SQL statements: %s", -+ (errmsg ? errmsg : "[???]")); -+ -+ apr_pool_destroy(rec->pool); -+ return rv; - } -- return rv; --} --static apr_status_t dbd_close(void *CONN) --{ -- ap_dbd_t *conn = CONN; -- apr_status_t rv = apr_dbd_close(conn->driver, conn->handle); -- apr_pool_destroy(conn->pool); -- return rv; -+ -+ *data_ptr = rec; -+ -+ return APR_SUCCESS; - } -+ - #if APR_HAS_THREADS --static apr_status_t dbd_destruct(void *sql, void *params, apr_pool_t *pool) -+static apr_status_t dbd_destroy(void *data) - { -- return dbd_close(sql); -+ dbd_group_t *group = data; -+ -+ group->destroyed = 1; -+ -+ return APR_SUCCESS; - } - --static apr_status_t dbd_setup(apr_pool_t *pool, svr_cfg *svr) -+static apr_status_t dbd_setup(server_rec *s, dbd_group_t *group) - { -+ dbd_cfg_t *cfg = group->cfg; - apr_status_t rv; - -- /* create a pool just for the reslist from a process-lifetime pool; -- * that pool (s->process->pool in the dbd_setup_lock case, -- * whatever was passed to ap_run_child_init in the dbd_setup_init case) -- * will be shared with other threads doing other non-mod_dbd things -- * so we can't use it for the reslist directly -+ /* We create the reslist using a sub-pool of the pool passed to our -+ * child_init hook. No other threads can be here because we're -+ * either in the child_init phase or dbd_setup_lock() acquired our mutex. -+ * No other threads will use this sub-pool after this, except via -+ * reslist calls, which have an internal mutex. -+ * -+ * We need to short-circuit the cleanup registered internally by -+ * apr_reslist_create(). We do this by registering dbd_destroy() -+ * as a cleanup afterwards, so that it will run before the reslist's -+ * internal cleanup. -+ * -+ * If we didn't do this, then we could free memory twice when the pool -+ * was destroyed. When apr_pool_destroy() runs, it first destroys all -+ * all the per-connection sub-pools created in dbd_construct(), and -+ * then it runs the reslist's cleanup. The cleanup calls dbd_destruct() -+ * on each resource, which would then attempt to destroy the sub-pools -+ * a second time. - */ -- rv = apr_pool_create(&svr->pool, pool); -+ rv = apr_reslist_create(&group->reslist, -+ cfg->nmin, cfg->nkeep, cfg->nmax, -+ apr_time_from_sec(cfg->exptime), -+ dbd_construct, dbd_destruct, group, -+ group->pool); - if (rv != APR_SUCCESS) { -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool, -- "DBD: Failed to create reslist memory pool"); -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, -+ "DBD: failed to initialise"); - return rv; - } - -- rv = apr_reslist_create(&svr->dbpool, svr->nmin, svr->nkeep, svr->nmax, -- apr_time_from_sec(svr->exptime), -- dbd_construct, dbd_destruct, svr, svr->pool); -- if (rv == APR_SUCCESS) { -- apr_pool_cleanup_register(svr->pool, svr->dbpool, -- (void*)apr_reslist_destroy, -- apr_pool_cleanup_null); -- } -- else { -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, svr->pool, -- "DBD: failed to initialise"); -- apr_pool_destroy(svr->pool); -- svr->pool = NULL; -- } -+ apr_pool_cleanup_register(group->pool, group, dbd_destroy, -+ apr_pool_cleanup_null); - -- return rv; -+ return APR_SUCCESS; - } -+#endif -+ - static apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s) - { -- svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); -- apr_status_t rv; -+ dbd_group_t *group; -+ apr_status_t rv = APR_SUCCESS; - -- /* dbd_setup in 2.2.3 and under was causing spurious error messages -- * when dbd isn't configured. We can stop that with a quick check here -- * together with a similar check in ap_dbd_open (where being -- * unconfigured is a genuine error that must be reported). -- */ -- if (svr->name == no_dbdriver) { -- return APR_SUCCESS; -- } -+ for (group = group_list; group; group = group->next) { -+ apr_status_t rv2; - -- if (!svr->persist) { -- return APR_SUCCESS; -- } -+ rv2 = apr_pool_create(&group->pool, pool); -+ if (rv2 != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s, -+ "DBD: Failed to create reslist cleanup memory pool"); -+ return rv2; -+ } - -- rv = dbd_setup(pool, svr); -- if (rv == APR_SUCCESS) { -- return rv; -- } -+#if APR_HAS_THREADS -+ rv2 = dbd_setup(s, group); -+ if (rv2 == APR_SUCCESS) { -+ continue; -+ } -+ else if (rv == APR_SUCCESS) { -+ rv = rv2; -+ } - -- /* we failed, so create a mutex so that subsequent competing callers -- * to ap_dbd_open can serialize themselves while they retry -- */ -- rv = apr_thread_mutex_create(&svr->mutex, APR_THREAD_MUTEX_DEFAULT, pool); -- if (rv != APR_SUCCESS) { -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool, -- "DBD: Failed to create thread mutex"); -+ /* we failed, so create a mutex so that subsequent competing callers -+ * to ap_dbd_open can serialize themselves while they retry -+ */ -+ rv2 = apr_thread_mutex_create(&group->mutex, -+ APR_THREAD_MUTEX_DEFAULT, pool); -+ if (rv2 != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv2, s, -+ "DBD: Failed to create thread mutex"); -+ return rv2; -+ } -+#endif - } -+ - return rv; - } --static apr_status_t dbd_setup_lock(apr_pool_t *pool, server_rec *s) -+ -+#if APR_HAS_THREADS -+static apr_status_t dbd_setup_lock(server_rec *s, dbd_group_t *group) - { -- svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); -- apr_status_t rv, rv2 = APR_SUCCESS; -+ apr_status_t rv = APR_SUCCESS, rv2; - - /* several threads could be here at the same time, all trying to - * initialize the reslist because dbd_setup_init failed to do so - */ -- if (!svr->mutex) { -+ if (!group->mutex) { - /* we already logged an error when the mutex couldn't be created */ - return APR_EGENERAL; - } - -- rv = apr_thread_mutex_lock(svr->mutex); -- if (rv != APR_SUCCESS) { -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool, -- "DBD: Failed to acquire thread mutex"); -- return rv; -- } -- -- if (!svr->dbpool) { -- rv2 = dbd_setup(s->process->pool, svr); -- } -- -- rv = apr_thread_mutex_unlock(svr->mutex); -- if (rv != APR_SUCCESS) { -- ap_log_perror(APLOG_MARK, APLOG_CRIT, rv, pool, -- "DBD: Failed to release thread mutex"); -- if (rv2 == APR_SUCCESS) { -- rv2 = rv; -+ rv2 = apr_thread_mutex_lock(group->mutex); -+ if (rv2 != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s, -+ "DBD: Failed to acquire thread mutex"); -+ return rv2; -+ } -+ -+ if (!group->reslist) { -+ rv = dbd_setup(s, group); -+ } -+ -+ rv2 = apr_thread_mutex_unlock(group->mutex); -+ if (rv2 != APR_SUCCESS) { -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv2, s, -+ "DBD: Failed to release thread mutex"); -+ if (rv == APR_SUCCESS) { -+ rv = rv2; - } - } -- return rv2; -+ -+ return rv; - } - #endif - -- - /* Functions we export for modules to use: - - open acquires a connection from the pool (opens one if necessary) - - close releases it back in to the pool - */ --DBD_DECLARE_NONSTD(void) ap_dbd_close(server_rec *s, ap_dbd_t *sql) -+DBD_DECLARE_NONSTD(void) ap_dbd_close(server_rec *s, ap_dbd_t *rec) - { - svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); -- if (!svr->persist) { -- dbd_close((void*) sql); -+ -+ if (!svr->cfg->persist) { -+ apr_pool_destroy(rec->pool); - } - #if APR_HAS_THREADS - else { -- apr_reslist_release(svr->dbpool, sql); -+ apr_reslist_release(svr->group->reslist, rec); - } - #endif - } --#define arec ((ap_dbd_t*)rec) --#if APR_HAS_THREADS -+ -+static apr_status_t dbd_check(apr_pool_t *pool, server_rec *s, ap_dbd_t *rec) -+{ -+ svr_cfg *svr; -+ apr_status_t rv = apr_dbd_check_conn(rec->driver, pool, rec->handle); -+ const char *errmsg; -+ -+ if ((rv == APR_SUCCESS) || (rv == APR_ENOTIMPL)) { -+ return APR_SUCCESS; -+ } -+ -+ /* we don't have a driver-specific error code, so we'll just pass -+ * a "success" value and rely on the driver to ignore it -+ */ -+ errmsg = apr_dbd_error(rec->driver, rec->handle, 0); -+ if (!errmsg) { -+ errmsg = "(unknown)"; -+ } -+ -+ svr = ap_get_module_config(s->module_config, &dbd_module); -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, -+ "DBD [%s] Error: %s", svr->cfg->name, errmsg); -+ return rv; -+} -+ - DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s) - { -- void *rec = NULL; - svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); -- apr_status_t rv = APR_SUCCESS; -- const char *errmsg; -+ dbd_group_t *group = svr->group; -+ dbd_cfg_t *cfg = svr->cfg; -+ ap_dbd_t *rec = NULL; -+#if APR_HAS_THREADS -+ apr_status_t rv; -+#endif - - /* If nothing is configured, we shouldn't be here */ -- if (svr->name == no_dbdriver) { -- ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "DBD: not configured"); -+ if (cfg->name == no_dbdriver) { -+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "DBD: not configured"); - return NULL; - } - -- if (!svr->persist) { -+ if (!cfg->persist) { - /* Return a once-only connection */ -- rv = dbd_construct(&rec, svr, s->process->pool); -- return (rv == APR_SUCCESS) ? arec : NULL; -+ group = apr_pcalloc(pool, sizeof(dbd_group_t)); -+ -+ group->cfg = cfg; -+ -+ dbd_construct((void*) &rec, group, pool); -+ return rec; - } - -- if (!svr->dbpool) { -- if (dbd_setup_lock(pool, s) != APR_SUCCESS) { -+#if APR_HAS_THREADS -+ if (!group->reslist) { -+ if (dbd_setup_lock(s, group) != APR_SUCCESS) { - return NULL; - } - } -- rv = apr_reslist_acquire(svr->dbpool, &rec); -+ -+ rv = apr_reslist_acquire(group->reslist, (void*) &rec); - if (rv != APR_SUCCESS) { -- ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool, -- "Failed to acquire DBD connection from pool!"); -+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, -+ "Failed to acquire DBD connection from pool!"); - return NULL; - } -- rv = apr_dbd_check_conn(arec->driver, pool, arec->handle); -- if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) { -- errmsg = apr_dbd_error(arec->driver, arec->handle, rv); -- if (!errmsg) { -- errmsg = "(unknown)"; -- } -- ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool, -- "DBD[%s] Error: %s", svr->name, errmsg ); -- apr_reslist_invalidate(svr->dbpool, rec); -+ -+ if (dbd_check(pool, s, rec) != APR_SUCCESS) { -+ apr_reslist_invalidate(group->reslist, rec); - return NULL; - } -- return arec; --} - #else --DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s) --{ -- apr_status_t rv = APR_SUCCESS; -- const char *errmsg; -- void *rec = NULL; -- svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); -- -- /* If nothing is configured, we shouldn't be here */ -- if (svr->name == no_dbdriver) { -- ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, "DBD: not configured"); -- return NULL; -+ /* If we have a persistent connection and it's good, we'll use it; -+ * since this is non-threaded, we can update without a mutex -+ */ -+ rec = group->rec; -+ if (rec) { -+ if (dbd_check(pool, s, rec) != APR_SUCCESS) { -+ apr_pool_destroy(rec->pool); -+ rec = NULL; -+ } - } - -- if (!svr->persist) { -- /* Return a once-only connection */ -- rv = dbd_construct(&rec, svr, s->process->pool); -- return (rv == APR_SUCCESS) ? arec : NULL; -+ /* We don't have a connection right now, so we'll open one */ -+ if (!rec) { -+ dbd_construct((void*) &rec, group, group->pool); -+ group->rec = rec; - } -+#endif - --/* since we're in nothread-land, we can mess with svr->conn with impunity */ --/* If we have a persistent connection and it's good, we'll use it */ -- if (svr->conn) { -- rv = apr_dbd_check_conn(svr->conn->driver, pool, svr->conn->handle); -- if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) { -- errmsg = apr_dbd_error(arec->driver, arec->handle, rv); -- if (!errmsg) { -- errmsg = "(unknown)"; -- } -- ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool, -- "DBD[%s] Error: %s", svr->name, errmsg); -- svr->conn = NULL; -- } -- } --/* We don't have a connection right now, so we'll open one */ -- if (!svr->conn) { -- if (dbd_construct(&rec, svr, s->process->pool) == APR_SUCCESS) { -- svr->conn = arec ; -- apr_pool_cleanup_register(s->process->pool, svr->conn, -- dbd_close, apr_pool_cleanup_null); -- } -- } -- return svr->conn; -+ return rec; - } --#endif -+ - #if APR_HAS_THREADS - typedef struct { -- ap_dbd_t *conn; -- apr_reslist_t *dbpool; --} dbd_pool_rec; --static apr_status_t dbd_release(void *REQ) -+ ap_dbd_t *rec; -+ apr_reslist_t *reslist; -+} dbd_acquire_t; -+ -+static apr_status_t dbd_release(void *data) - { -- dbd_pool_rec *req = REQ; -- apr_reslist_release(req->dbpool, req->conn); -+ dbd_acquire_t *acq = data; -+ apr_reslist_release(acq->reslist, acq->rec); - return APR_SUCCESS; - } -+ - DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r) - { -- svr_cfg *svr; -- dbd_pool_rec *req; -+ dbd_acquire_t *acq; - - while (!ap_is_initial_req(r)) { - if (r->prev) { -@@ -557,54 +812,52 @@ DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_ac - } - } - -- req = ap_get_module_config(r->request_config, &dbd_module); -- if (!req) { -- req = apr_palloc(r->pool, sizeof(dbd_pool_rec)); -- req->conn = ap_dbd_open(r->pool, r->server); -- if (req->conn) { -- svr = ap_get_module_config(r->server->module_config, &dbd_module); -- ap_set_module_config(r->request_config, &dbd_module, req); -- if (svr->persist) { -- req->dbpool = svr->dbpool; -- apr_pool_cleanup_register(r->pool, req, dbd_release, -- apr_pool_cleanup_null); -- } -- else { -- apr_pool_cleanup_register(r->pool, req->conn, dbd_close, -+ acq = ap_get_module_config(r->request_config, &dbd_module); -+ if (!acq) { -+ acq = apr_palloc(r->pool, sizeof(dbd_acquire_t)); -+ acq->rec = ap_dbd_open(r->pool, r->server); -+ if (acq->rec) { -+ svr_cfg *svr = ap_get_module_config(r->server->module_config, -+ &dbd_module); -+ -+ ap_set_module_config(r->request_config, &dbd_module, acq); -+ if (svr->cfg->persist) { -+ acq->reslist = svr->group->reslist; -+ apr_pool_cleanup_register(r->pool, acq, dbd_release, - apr_pool_cleanup_null); - } - } - } -- return req->conn; -+ -+ return acq->rec; - } -+ - DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c) - { -- svr_cfg *svr; -- dbd_pool_rec *req = ap_get_module_config(c->conn_config, &dbd_module); -- if (!req) { -- req = apr_palloc(c->pool, sizeof(dbd_pool_rec)); -- req->conn = ap_dbd_open(c->pool, c->base_server); -- if (req->conn) { -- svr = ap_get_module_config(c->base_server->module_config, &dbd_module); -- ap_set_module_config(c->conn_config, &dbd_module, req); -- if (svr->persist) { -- req->dbpool = svr->dbpool; -- apr_pool_cleanup_register(c->pool, req, dbd_release, -- apr_pool_cleanup_null); -- } -- else { -- apr_pool_cleanup_register(c->pool, req->conn, dbd_close, -+ dbd_acquire_t *acq = ap_get_module_config(c->conn_config, &dbd_module); -+ -+ if (!acq) { -+ acq = apr_palloc(c->pool, sizeof(dbd_acquire_t)); -+ acq->rec = ap_dbd_open(c->pool, c->base_server); -+ if (acq->rec) { -+ svr_cfg *svr = ap_get_module_config(c->base_server->module_config, -+ &dbd_module); -+ -+ ap_set_module_config(c->conn_config, &dbd_module, acq); -+ if (svr->cfg->persist) { -+ acq->reslist = svr->group->reslist; -+ apr_pool_cleanup_register(c->pool, acq, dbd_release, - apr_pool_cleanup_null); - } - } - } -- return req->conn; -+ -+ return acq->rec; - } - #else - DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_acquire(request_rec *r) - { -- svr_cfg *svr; -- ap_dbd_t *ret; -+ ap_dbd_t *rec; - - while (!ap_is_initial_req(r)) { - if (r->prev) { -@@ -615,80 +868,54 @@ DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_ac - } - } - -- ret = ap_get_module_config(r->request_config, &dbd_module); -- if (!ret) { -- svr = ap_get_module_config(r->server->module_config, &dbd_module); -- ret = ap_dbd_open(r->pool, r->server); -- if (ret) { -- ap_set_module_config(r->request_config, &dbd_module, ret); -- if (!svr->persist) { -- apr_pool_cleanup_register(r->pool, svr->conn, dbd_close, -- apr_pool_cleanup_null); -- } -- /* if persist then dbd_open registered cleanup on proc pool */ -+ rec = ap_get_module_config(r->request_config, &dbd_module); -+ if (!rec) { -+ rec = ap_dbd_open(r->pool, r->server); -+ if (rec) { -+ ap_set_module_config(r->request_config, &dbd_module, rec); - } - } -- return ret; -+ -+ return rec; - } -+ - DBD_DECLARE_NONSTD(ap_dbd_t *) ap_dbd_cacquire(conn_rec *c) - { -- svr_cfg *svr; -- ap_dbd_t *ret = ap_get_module_config(c->conn_config, &dbd_module); -- if (!ret) { -- svr = ap_get_module_config(c->base_server->module_config, &dbd_module); -- ret = ap_dbd_open(c->pool, c->base_server); -- if (ret) { -- ap_set_module_config(c->conn_config, &dbd_module, ret); -- if (!svr->persist) { -- apr_pool_cleanup_register(c->pool, svr->conn, dbd_close, -- apr_pool_cleanup_null); -- } -- /* if persist then dbd_open registered cleanup on proc pool */ -+ ap_dbd_t *rec = ap_get_module_config(c->conn_config, &dbd_module); -+ -+ if (!rec) { -+ rec = ap_dbd_open(c->pool, c->base_server); -+ if (rec) { -+ ap_set_module_config(c->conn_config, &dbd_module, rec); - } - } -- return ret; -+ -+ return rec; - } - #endif - --static int dbd_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp) --{ -- dbd_prepared_defns = apr_hash_make(ptemp); -- return OK; --} --static int dbd_post_config(apr_pool_t *pconf, apr_pool_t *plog, -- apr_pool_t *ptemp, server_rec *s) --{ -- svr_cfg *svr; -- server_rec *sp; -- for (sp = s; sp; sp = sp->next) { -- const char *key = apr_psprintf(s->process->pool, "%pp", s); -- svr = ap_get_module_config(sp->module_config, &dbd_module); -- svr->prepared = apr_hash_get(dbd_prepared_defns, key, -- APR_HASH_KEY_STRING); -- } -- return OK; --} - static void dbd_hooks(apr_pool_t *pool) - { --#if APR_HAS_THREADS -+ ap_hook_pre_config(dbd_pre_config, NULL, NULL, APR_HOOK_MIDDLE); -+ ap_hook_post_config(dbd_post_config, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_child_init((void*)dbd_setup_init, NULL, NULL, APR_HOOK_MIDDLE); --#endif -+ -+ APR_REGISTER_OPTIONAL_FN(ap_dbd_prepare); - APR_REGISTER_OPTIONAL_FN(ap_dbd_open); - APR_REGISTER_OPTIONAL_FN(ap_dbd_close); - APR_REGISTER_OPTIONAL_FN(ap_dbd_acquire); - APR_REGISTER_OPTIONAL_FN(ap_dbd_cacquire); -- APR_REGISTER_OPTIONAL_FN(ap_dbd_prepare); -+ - apr_dbd_init(pool); -- ap_hook_pre_config(dbd_pre_config, NULL, NULL, APR_HOOK_MIDDLE); -- ap_hook_post_config(dbd_post_config, NULL, NULL, APR_HOOK_MIDDLE); - } - - module AP_MODULE_DECLARE_DATA dbd_module = { - STANDARD20_MODULE_STUFF, - NULL, - NULL, -- dbd_cfg, -- dbd_merge, -+ create_dbd_config, -+ merge_dbd_config, - dbd_cmds, - dbd_hooks - }; -+ diff --git a/2.2/patches/20_all_peruser_0.2.1.patch b/2.2/patches/20_all_peruser_0.2.2.patch index 93d2028..adcfd14 100644 --- a/2.2/patches/20_all_peruser_0.2.1.patch +++ b/2.2/patches/20_all_peruser_0.2.2.patch @@ -1,6 +1,6 @@ diff -Nur httpd-2.2.3/server/mpm/config.m4 httpd-2.2.3-new/server/mpm/config.m4 --- httpd-2.2.3/server/mpm/config.m4 2005-10-30 10:05:26.000000000 -0700 -+++ httpd-2.2.3-new/server/mpm/config.m4 2007-02-05 06:47:03.000000000 -0700 ++++ httpd-2.2.3-new/server/mpm/config.m4 2007-08-17 18:23:23.000000000 -0600 @@ -1,7 +1,7 @@ AC_MSG_CHECKING(which MPM to use) AC_ARG_WITH(mpm, @@ -21,7 +21,7 @@ diff -Nur httpd-2.2.3/server/mpm/config.m4 httpd-2.2.3-new/server/mpm/config.m4 return 1 diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/Makefile.in httpd-2.2.3-new/server/mpm/experimental/peruser/Makefile.in --- httpd-2.2.3/server/mpm/experimental/peruser/Makefile.in 1969-12-31 17:00:00.000000000 -0700 -+++ httpd-2.2.3-new/server/mpm/experimental/peruser/Makefile.in 2007-02-05 06:47:03.000000000 -0700 ++++ httpd-2.2.3-new/server/mpm/experimental/peruser/Makefile.in 2007-08-17 18:23:23.000000000 -0600 @@ -0,0 +1,5 @@ + +LTLIBRARY_NAME = libperuser.la @@ -30,14 +30,14 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/Makefile.in httpd-2.2.3-ne +include $(top_srcdir)/build/ltlib.mk diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/config.m4 httpd-2.2.3-new/server/mpm/experimental/peruser/config.m4 --- httpd-2.2.3/server/mpm/experimental/peruser/config.m4 1969-12-31 17:00:00.000000000 -0700 -+++ httpd-2.2.3-new/server/mpm/experimental/peruser/config.m4 2007-02-05 06:47:03.000000000 -0700 ++++ httpd-2.2.3-new/server/mpm/experimental/peruser/config.m4 2007-08-17 18:23:23.000000000 -0600 @@ -0,0 +1,3 @@ +if test "$MPM_NAME" = "peruser" ; then + APACHE_FAST_OUTPUT(server/mpm/experimental/$MPM_NAME/Makefile) +fi diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/mpm.h httpd-2.2.3-new/server/mpm/experimental/peruser/mpm.h --- httpd-2.2.3/server/mpm/experimental/peruser/mpm.h 1969-12-31 17:00:00.000000000 -0700 -+++ httpd-2.2.3-new/server/mpm/experimental/peruser/mpm.h 2007-02-05 06:47:03.000000000 -0700 ++++ httpd-2.2.3-new/server/mpm/experimental/peruser/mpm.h 2007-08-17 18:23:23.000000000 -0600 @@ -0,0 +1,103 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 @@ -144,7 +144,7 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/mpm.h httpd-2.2.3-new/serv +#endif /* APACHE_MPM_PERUSER_H */ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/mpm_default.h httpd-2.2.3-new/server/mpm/experimental/peruser/mpm_default.h --- httpd-2.2.3/server/mpm/experimental/peruser/mpm_default.h 1969-12-31 17:00:00.000000000 -0700 -+++ httpd-2.2.3-new/server/mpm/experimental/peruser/mpm_default.h 2007-02-05 06:47:03.000000000 -0700 ++++ httpd-2.2.3-new/server/mpm/experimental/peruser/mpm_default.h 2007-08-17 18:23:23.000000000 -0600 @@ -0,0 +1,110 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 @@ -258,8 +258,8 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/mpm_default.h httpd-2.2.3- +#endif /* AP_MPM_DEFAULT_H */ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/server/mpm/experimental/peruser/peruser.c --- httpd-2.2.3/server/mpm/experimental/peruser/peruser.c 1969-12-31 17:00:00.000000000 -0700 -+++ httpd-2.2.3-new/server/mpm/experimental/peruser/peruser.c 2007-02-05 07:16:52.000000000 -0700 -@@ -0,0 +1,3006 @@ ++++ httpd-2.2.3-new/server/mpm/experimental/peruser/peruser.c 2007-08-17 18:23:59.000000000 -0600 +@@ -0,0 +1,3130 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * @@ -526,6 +526,16 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + +typedef struct +{ ++ /* identification */ ++ int id; /* index in child_info_table */ ++ pid_t pid; /* process id */ ++ int status; /* status of child */ ++ int type; /* multiplexer or processor */ ++ apr_time_t last_used; ++} child_grace_info_t; ++ ++typedef struct ++{ + apr_size_t num; +} child_info_control; + @@ -535,7 +545,6 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + child_info_t *table; +} child_info; + -+ +typedef struct +{ + server_env_t *senv; @@ -555,6 +564,7 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + */ +static apr_size_t child_info_size; +static child_info *child_info_image; ++static child_grace_info_t *child_grace_info_table; +struct ap_ctable *ap_child_table; + +#define NUM_CHILDS (child_info_image != NULL ? child_info_image->control->num : 0) @@ -617,6 +627,9 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + +static int die_now = 0; + ++int grace_children = 0; ++int grace_children_alive = 0; ++ +#ifdef GPROF +/* + * change directory for gprof to plop the gmon.out file @@ -2047,18 +2060,18 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + child_info_t *this; + child_info_t *new; + -+ if(NUM_CHILDS >= server_limit) -+ { -+ _DBG("Trying to use more child ID's than NumServers. " -+ "Increase NumServers in your config file."); -+ return NULL; -+ } -+ + for(i = 0; i < NUM_CHILDS; i++) + { + if(CHILD_INFO_TABLE[i].pid == 0 && + CHILD_INFO_TABLE[i].type == CHILD_TYPE_UNKNOWN) break; + } ++ ++ if(i == NUM_CHILDS && NUM_CHILDS >= server_limit) ++ { ++ _DBG("Trying to use more child ID's than NumServers. " ++ "Increase NumServers in your config file."); ++ return NULL; ++ } + + _DBG("cloning child #%d from #%d", i, my_child_num); + @@ -2289,8 +2302,48 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + ap_update_child_status_from_indexes(i, 0, SERVER_DEAD, NULL); + } + } ++ ++ for(i=0;i<grace_children;i++) { ++ if (child_grace_info_table[i].pid > 0 && ++ apr_time_sec(now - child_grace_info_table[i].last_used) > expire_timeout) { ++ ++ _DBG("Killing a child from last graceful (pid=%d,childno=%d,last_used=%d)", ++ child_grace_info_table[i].pid, child_grace_info_table[i].id, ++ child_grace_info_table[i].last_used); ++ ++ if(kill(child_grace_info_table[i].pid, SIGTERM) == -1) ++ { ++ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, ++ ap_server_conf, "kill SIGTERM"); ++ } ++ ++ /* We don't need to do remove_grace_child() here, ++ * because it will be automatically done once ++ * the child dies by ap_mpm_run() */ ++ } ++ } +} + ++int remove_grace_child(int slot) { ++ if (slot < grace_children) { ++ child_grace_info_table[slot].id = 0; ++ child_grace_info_table[slot].pid = 0; ++ child_grace_info_table[slot].status = CHILD_STATUS_STANDBY; ++ child_grace_info_table[slot].type = CHILD_TYPE_UNKNOWN; ++ child_grace_info_table[slot].last_used = 0; ++ grace_children_alive--; ++ ++ if (grace_children_alive <= 0) { /* All children have returned from graceful */ ++ _DBG("Every child has returned from graceful restart - freeing child_grace_info_table"); ++ grace_children_alive = 0; ++ is_graceful = 0; ++ grace_children = 0; ++ free(child_grace_info_table); ++ } ++ return 0; ++ } ++ return 1; ++} + +/***************************************************************** + * Executive routines. @@ -2424,6 +2477,19 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + mpm_state = AP_MPMQ_STOPPING; + return 1; + } ++ ++ if (grace_children > 0) { ++ for(i=0;i<grace_children;i++) { ++ if (child_grace_info_table[i].pid == pid.pid) { ++ break; ++ } ++ } ++ if (i != grace_children) { ++ _DBG("Child returned from graceful (%d)", i); ++ remove_grace_child(i); ++ continue; ++ } ++ } + + /* non-fatal death... note that it's gone in the scoreboard. */ + child_slot = find_child_by_pid(&pid); @@ -2569,9 +2635,42 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + * gracefully dealing with existing request. + */ + ++ int alivechildren = 0; ++ int child_grace_info_size; ++ child_grace_info_t* old_grace_info; ++ void* mem; ++ + for (i = 0; i < NUM_CHILDS; ++i) + { + ((ap_child_table[i].pid) && (ap_child_table[i].status = SERVER_DYING)); ++ ++ if (CHILD_INFO_TABLE[i].pid) { ++ alivechildren++; ++ } ++ } ++ ++ _DBG("Initializing child_grace_info_table", 0); ++ ++ if (alivechildren > 0) { ++ if (grace_children > 0) { ++ old_grace_info = child_grace_info_table; ++ _DBG("%d children still living from last graceful " ++ "- adding to new child_grace_info_table", ++ grace_children); ++ } ++ ++ child_grace_info_table = (child_grace_info_t*)calloc(alivechildren+grace_children, ++ sizeof(child_grace_info_t)); ++ ++ if (grace_children > 0) { ++ for(i=0;i<grace_children;i++) { ++ child_grace_info_table[i] = old_grace_info[i]; ++ } ++ grace_children = i; ++ free(old_grace_info); ++ } ++ else grace_children = 0; ++ + } + + /* give the children the signal to die */ @@ -2583,8 +2682,19 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, + "write pipe_of_death"); + } ++ if (CHILD_INFO_TABLE[i].pid) { ++ child_grace_info_table[grace_children].id = CHILD_INFO_TABLE[i].id; ++ child_grace_info_table[grace_children].pid = CHILD_INFO_TABLE[i].pid; ++ child_grace_info_table[grace_children].status = CHILD_INFO_TABLE[i].status; ++ child_grace_info_table[grace_children].type = CHILD_INFO_TABLE[i].type; ++ child_grace_info_table[grace_children].last_used = ap_scoreboard_image->servers[i][0].last_used; ++ grace_children++; ++ grace_children_alive++; ++ } + i++; + } ++ _DBG("Total children of %d leaving behind for graceful restart (%d living)", ++ grace_children, grace_children_alive); + + for (i = 0; i < NUM_SENV; i++) + { @@ -2654,9 +2764,9 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + return OK; +} + ++static int restart_num = 0; +static int peruser_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp) +{ -+ static int restart_num = 0; + int no_detach, debug, foreground, i; + int tmp_server_limit = DEFAULT_SERVER_LIMIT; + ap_directive_t *pdir; @@ -2681,8 +2791,6 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + + /* sigh, want this only the second time around */ + if (restart_num++ == 1) { -+ is_graceful = 0; -+ + if (!one_process && !foreground) { + rv = apr_proc_detach(no_detach ? APR_PROC_DETACH_FOREGROUND + : APR_PROC_DETACH_DAEMONIZE); @@ -2952,6 +3060,22 @@ diff -Nur httpd-2.2.3/server/mpm/experimental/peruser/peruser.c httpd-2.2.3-new/ + ); + } + ap_rputs("</table>\n", r); ++ ++ if (grace_children > 0) { ++ ap_rputs("<h2>peruser graceful children status</h2>\n", r); ++ ap_rprintf(r, "%d of total %d still living<br />\n", grace_children_alive, grace_children); ++ ap_rputs("<table border=\"0\">\n", r); ++ ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>TYPE</td></tr>\n", r); ++ for (x = 0; x < grace_children; x++) { ++ ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%12s</td></tr>\n", ++ child_grace_info_table[x].id, ++ child_grace_info_table[x].pid, ++ child_status_string(child_grace_info_table[x].status), ++ child_type_string(child_grace_info_table[x].type) ++ ); ++ } ++ ap_rputs("</table>\n", r); ++ } + return OK; +} + diff --git a/2.2/patches/21_all_itk_20070425-00.patch b/2.2/patches/21_all_itk_20070425-00.patch index 449a5e1..58c9706 100644 --- a/2.2/patches/21_all_itk_20070425-00.patch +++ b/2.2/patches/21_all_itk_20070425-00.patch @@ -11,7 +11,7 @@ Index: httpd-2.2.4/server/mpm/config.m4 APACHE_MPM=$withval ],[ if test "x$APACHE_MPM" = "x"; then -@@ -23,7 +23,7 @@ ap_mpm_is_threaded () +@@ -23,7 +23,7 @@ ap_mpm_is_experimental () { @@ -20,7 +20,7 @@ Index: httpd-2.2.4/server/mpm/config.m4 return 0 else return 1 -@@ -66,6 +66,11 @@ if ap_mpm_is_experimental; then +@@ -66,6 +66,11 @@ else MPM_SUBDIR_NAME=$MPM_NAME fi @@ -33,7 +33,6 @@ Index: httpd-2.2.4/server/mpm/config.m4 MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la Index: httpd-2.2.4/server/mpm/experimental/itk/config.m4 -=================================================================== --- /dev/null +++ httpd-2.2.4/server/mpm/experimental/itk/config.m4 @@ -0,0 +1,3 @@ @@ -41,7 +40,6 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/config.m4 + APACHE_FAST_OUTPUT(server/mpm/$MPM_SUBDIR_NAME/Makefile) +fi Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c -=================================================================== --- /dev/null +++ httpd-2.2.4/server/mpm/experimental/itk/itk.c @@ -0,0 +1,1682 @@ @@ -1246,7 +1244,7 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c + for (index = 0; index < ap_daemons_limit; ++index) { + if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { + /* Ask each child to close its listeners. */ -+ kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL); ++ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL); + active_children++; + } + } @@ -1284,13 +1282,13 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c + + active_children = 0; + for (index = 0; index < ap_daemons_limit; ++index) { -+ if (MPM_CHILD_PID(index) != 0) { -+ if (kill(MPM_CHILD_PID(index), 0) == 0) { ++ //if (MPM_CHILD_PID(index) != 0) { ++ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { + active_children = 1; + /* Having just one child is enough to stay around */ + break; + } -+ } ++ //} + } + } while (!shutdown_pending && active_children && + (!ap_graceful_shutdown_timeout || apr_time_now() < cutoff)); @@ -1341,7 +1339,7 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c + * piped loggers, etc. They almost certainly won't handle + * it gracefully. + */ -+ kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); ++ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); + } + } + } @@ -1738,7 +1736,6 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/Makefile.in + +include $(top_srcdir)/build/ltlib.mk Index: httpd-2.2.4/server/mpm/experimental/itk/mpm_default.h -=================================================================== --- /dev/null +++ httpd-2.2.4/server/mpm/experimental/itk/mpm_default.h @@ -0,0 +1,77 @@ @@ -1820,7 +1817,6 @@ Index: httpd-2.2.4/server/mpm/experimental/itk/mpm_default.h +#endif /* AP_MPM_DEFAULT_H */ +/** @} */ Index: httpd-2.2.4/server/mpm/experimental/itk/mpm.h -=================================================================== --- /dev/null +++ httpd-2.2.4/server/mpm/experimental/itk/mpm.h @@ -0,0 +1,65 @@ diff --git a/2.2/patches/80_all_CVE-2006-5752.patch b/2.2/patches/80_all_CVE-2006-5752.patch deleted file mode 100644 index cbf3297..0000000 --- a/2.2/patches/80_all_CVE-2006-5752.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- httpd-2.2.3/modules/generators/mod_status.c.cve5752 -+++ httpd-2.2.3/modules/generators/mod_status.c -@@ -270,7 +270,7 @@ - if (r->method_number != M_GET) - return DECLINED; - -- ap_set_content_type(r, "text/html"); -+ ap_set_content_type(r, "text/html; charset=ISO-8859-1"); - - /* - * Simple table-driven form data set parser that lets you alter the header -@@ -299,7 +299,7 @@ - no_table_report = 1; - break; - case STAT_OPT_AUTO: -- ap_set_content_type(r, "text/plain"); -+ ap_set_content_type(r, "text/plain; charset=ISO-8859-1"); - short_report = 1; - break; - } -@@ -673,7 +673,8 @@ - ap_escape_html(r->pool, - ws_record->client), - ap_escape_html(r->pool, -- ws_record->request), -+ ap_escape_logitem(r->pool, -+ ws_record->request)), - ap_escape_html(r->pool, - ws_record->vhost)); - } -@@ -763,7 +764,8 @@ - ap_escape_html(r->pool, - ws_record->vhost), - ap_escape_html(r->pool, -- ws_record->request)); -+ ap_escape_logitem(r->pool, -+ ws_record->request))); - } /* no_table_report */ - } /* for (j...) */ - } /* for (i...) */ diff --git a/2.2/patches/81_all_CVE-2007-1862.patch b/2.2/patches/81_all_CVE-2007-1862.patch deleted file mode 100644 index 17e6cc5..0000000 --- a/2.2/patches/81_all_CVE-2007-1862.patch +++ /dev/null @@ -1,51 +0,0 @@ ---- httpd-2.2.4/modules/cache/mod_mem_cache.c.cve1862 -+++ httpd-2.2.4/modules/cache/mod_mem_cache.c -@@ -539,12 +539,28 @@ - return OK; - } - -+static apr_table_t *deep_table_copy(apr_pool_t *p, const apr_table_t *table) -+{ -+ const apr_array_header_t *array = apr_table_elts(table); -+ apr_table_entry_t *elts = (apr_table_entry_t *) array->elts; -+ apr_table_t *copy = apr_table_make(p, array->nelts); -+ int i; -+ -+ for (i = 0; i < array->nelts; i++) { -+ if (elts[i].key) { -+ apr_table_add(copy, elts[i].key, elts[i].val); -+ } -+ } -+ -+ return copy; -+} -+ - static apr_status_t recall_headers(cache_handle_t *h, request_rec *r) - { - mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj; - -- h->req_hdrs = apr_table_copy(r->pool, mobj->req_hdrs); -- h->resp_hdrs = apr_table_copy(r->pool, mobj->header_out); -+ h->req_hdrs = deep_table_copy(r->pool, mobj->req_hdrs); -+ h->resp_hdrs = deep_table_copy(r->pool, mobj->header_out); - - return OK; - } -@@ -585,7 +601,7 @@ - * - The original response headers (for returning with a cached response) - * - The body of the message - */ -- mobj->req_hdrs = apr_table_copy(mobj->pool, r->headers_in); -+ mobj->req_hdrs = deep_table_copy(mobj->pool, r->headers_in); - - /* Precompute how much storage we need to hold the headers */ - headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out, -@@ -599,7 +615,7 @@ - } - - headers_out = apr_table_overlay(r->pool, headers_out, r->err_headers_out); -- mobj->header_out = apr_table_copy(mobj->pool, headers_out); -+ mobj->header_out = deep_table_copy(mobj->pool, headers_out); - - /* Init the info struct */ - obj->info.status = info->status; diff --git a/2.2/patches/82_all_CVE-2007-1863.patch b/2.2/patches/82_all_CVE-2007-1863.patch deleted file mode 100644 index 41c3ba7..0000000 --- a/2.2/patches/82_all_CVE-2007-1863.patch +++ /dev/null @@ -1,74 +0,0 @@ ---- httpd-2.2.3/modules/cache/cache_util.c.cve1863 -+++ httpd-2.2.3/modules/cache/cache_util.c -@@ -231,7 +231,8 @@ - age = ap_cache_current_age(info, age_c, r->request_time); - - /* extract s-maxage */ -- if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val)) { -+ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "s-maxage", &val) -+ && val != NULL) { - smaxage = apr_atoi64(val); - } - else { -@@ -240,7 +241,8 @@ - - /* extract max-age from request */ - if (!conf->ignorecachecontrol -- && cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val)) { -+ && cc_req && ap_cache_liststr(r->pool, cc_req, "max-age", &val) -+ && val != NULL) { - maxage_req = apr_atoi64(val); - } - else { -@@ -248,7 +250,8 @@ - } - - /* extract max-age from response */ -- if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val)) { -+ if (cc_cresp && ap_cache_liststr(r->pool, cc_cresp, "max-age", &val) -+ && val != NULL) { - maxage_cresp = apr_atoi64(val); - } - else { -@@ -270,7 +273,20 @@ - - /* extract max-stale */ - if (cc_req && ap_cache_liststr(r->pool, cc_req, "max-stale", &val)) { -- maxstale = apr_atoi64(val); -+ if(val != NULL) { -+ maxstale = apr_atoi64(val); -+ } -+ else { -+ /* -+ * If no value is assigned to max-stale, then the client is willing -+ * to accept a stale response of any age (RFC2616 14.9.3). We will -+ * set it to one year in this case as this situation is somewhat -+ * similar to a "never expires" Expires header (RFC2616 14.21) -+ * which is set to a date one year from the time the response is -+ * sent in this case. -+ */ -+ maxstale = APR_INT64_C(86400*365); -+ } - } - else { - maxstale = 0; -@@ -278,7 +294,8 @@ - - /* extract min-fresh */ - if (!conf->ignorecachecontrol -- && cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val)) { -+ && cc_req && ap_cache_liststr(r->pool, cc_req, "min-fresh", &val) -+ && val != NULL) { - minfresh = apr_atoi64(val); - } - else { -@@ -407,6 +424,9 @@ - next - val_start); - } - } -+ else { -+ *val = NULL; -+ } - } - return 1; - } diff --git a/2.2/patches/83_all_CVE-2007-3304.patch b/2.2/patches/83_all_CVE-2007-3304.patch deleted file mode 100644 index 7337d6a..0000000 --- a/2.2/patches/83_all_CVE-2007-3304.patch +++ /dev/null @@ -1,261 +0,0 @@ -Index: httpd-2.2.4/server/mpm/prefork/prefork.c -=================================================================== ---- httpd-2.2.4.orig/server/mpm/prefork/prefork.c -+++ httpd-2.2.4/server/mpm/prefork/prefork.c -@@ -1127,7 +1127,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p - for (index = 0; index < ap_daemons_limit; ++index) { - if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { - /* Ask each child to close its listeners. */ -- kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL); -+ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL); - active_children++; - } - } -@@ -1165,12 +1165,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p - - active_children = 0; - for (index = 0; index < ap_daemons_limit; ++index) { -- if (MPM_CHILD_PID(index) != 0) { -- if (kill(MPM_CHILD_PID(index), 0) == 0) { -- active_children = 1; -- /* Having just one child is enough to stay around */ -- break; -- } -+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { -+ active_children = 1; -+ /* Having just one child is enough to stay around */ -+ break; - } - } - } while (!shutdown_pending && active_children && -@@ -1222,7 +1220,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p - * piped loggers, etc. They almost certainly won't handle - * it gracefully. - */ -- kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); -+ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); - } - } - } -Index: httpd-2.2.4/server/mpm/worker/worker.c -=================================================================== ---- httpd-2.2.4.orig/server/mpm/worker/worker.c -+++ httpd-2.2.4/server/mpm/worker/worker.c -@@ -1813,12 +1813,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p - - active_children = 0; - for (index = 0; index < ap_daemons_limit; ++index) { -- if (MPM_CHILD_PID(index) != 0) { -- if (kill(MPM_CHILD_PID(index), 0) == 0) { -- active_children = 1; -- /* Having just one child is enough to stay around */ -- break; -- } -+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { -+ active_children = 1; -+ /* Having just one child is enough to stay around */ -+ break; - } - } - } while (!shutdown_pending && active_children && -Index: httpd-2.2.4/server/mpm/experimental/event/event.c -=================================================================== ---- httpd-2.2.4.orig/server/mpm/experimental/event/event.c -+++ httpd-2.2.4/server/mpm/experimental/event/event.c -@@ -1998,12 +1998,10 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_ - - active_children = 0; - for (index = 0; index < ap_daemons_limit; ++index) { -- if (MPM_CHILD_PID(index) != 0) { -- if (kill(MPM_CHILD_PID(index), 0) == 0) { -- active_children = 1; -- /* Having just one child is enough to stay around */ -- break; -- } -+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { -+ active_children = 1; -+ /* Having just one child is enough to stay around */ -+ break; - } - } - } while (!shutdown_pending && active_children && -Index: httpd-2.2.4/server/mpm_common.c -=================================================================== ---- httpd-2.2.4.orig/server/mpm_common.c -+++ httpd-2.2.4/server/mpm_common.c -@@ -126,6 +126,11 @@ static int reclaim_one_pid(pid_t pid, ac - apr_proc_t proc; - apr_status_t waitret; - -+ /* Ensure pid sanity. */ -+ if (pid < 1) { -+ return 1; -+ } -+ - proc.pid = pid; - waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT); - if (waitret != APR_CHILD_NOTDONE) { -@@ -305,6 +310,66 @@ void ap_relieve_child_processes(void) - cur_extra = next; - } - } -+ -+/* Before sending the signal to the pid this function verifies that -+ * the pid is a member of the current process group; either using -+ * apr_proc_wait(), where waitpid() guarantees to fail for non-child -+ * processes; or by using getpgid() directly, if available. */ -+apr_status_t ap_mpm_safe_kill(pid_t pid, int sig) -+{ -+#ifndef HAVE_GETPGID -+ apr_proc_t proc; -+ apr_status_t rv; -+ apr_exit_why_e why; -+ int status; -+ -+ /* Ensure pid sanity */ -+ if (pid < 1) { -+ return APR_EINVAL; -+ } -+ -+ proc.pid = pid; -+ rv = apr_proc_wait(&proc, &status, &why, APR_NOWAIT); -+ if (rv == APR_CHILD_DONE) { -+#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS -+ /* The child already died - log the termination status if -+ * necessary: */ -+ ap_process_child_status(&proc, why, status); -+#endif -+ return APR_EINVAL; -+ } -+ else if (rv != APR_CHILD_NOTDONE) { -+ /* The child is already dead and reaped, or was a bogus pid - -+ * log this either way. */ -+ ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf, -+ "cannot send signal %d to pid %ld (non-child or " -+ "already dead)", sig, (long)pid); -+ return APR_EINVAL; -+ } -+#else -+ pid_t pg; -+ -+ /* Ensure pid sanity. */ -+ if (pid < 1) { -+ return APR_EINVAL; -+ } -+ -+ pg = getpgid(pid); -+ if (pg == -1) { -+ /* Process already dead... */ -+ return errno; -+ } -+ -+ if (pg != getpgrp()) { -+ ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf, -+ "refusing to send signal %d to pid %ld outside " -+ "process group", sig, (long)pid); -+ return APR_EINVAL; -+ } -+#endif -+ -+ return kill(pid, sig) ? errno : APR_SUCCESS; -+} - #endif /* AP_MPM_WANT_RECLAIM_CHILD_PROCESSES */ - - #ifdef AP_MPM_WANT_WAIT_OR_TIMEOUT -Index: httpd-2.2.4/include/mpm_common.h -=================================================================== ---- httpd-2.2.4.orig/include/mpm_common.h -+++ httpd-2.2.4/include/mpm_common.h -@@ -145,6 +145,19 @@ int ap_unregister_extra_mpm_process(pid_ - #endif - - /** -+ * Safely signal an MPM child process, if the process is in the -+ * current process group. Otherwise fail. -+ * @param pid the process id of a child process to signal -+ * @param sig the signal number to send -+ * @return APR_SUCCESS if signal is sent, otherwise an error as per kill(3); -+ * APR_EINVAL is returned if passed either an invalid (< 1) pid, or if -+ * the pid is not in the current process group -+ */ -+#ifdef AP_MPM_WANT_RECLAIM_CHILD_PROCESSES -+apr_status_t ap_mpm_safe_kill(pid_t pid, int sig); -+#endif -+ -+/** - * Determine if any child process has died. If no child process died, then - * this process sleeps for the amount of time specified by the MPM defined - * macro SCOREBOARD_MAINTENANCE_INTERVAL. -Index: httpd-2.2.4/include/ap_mmn.h -=================================================================== ---- httpd-2.2.4.orig/include/ap_mmn.h -+++ httpd-2.2.4/include/ap_mmn.h -@@ -113,6 +113,8 @@ - * 20051115.3 (2.2.3) Added server_scheme member to server_rec (minor) - * 20051115.4 (2.2.4) Added ap_get_server_banner() and - * ap_get_server_description() (minor) -+ * 20051115.5 (2.2.5) Added ap_mpm_safe_kill() (minor) -+ * - */ - - #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */ -@@ -120,7 +122,7 @@ - #ifndef MODULE_MAGIC_NUMBER_MAJOR - #define MODULE_MAGIC_NUMBER_MAJOR 20051115 - #endif --#define MODULE_MAGIC_NUMBER_MINOR 4 /* 0...n */ -+#define MODULE_MAGIC_NUMBER_MINOR 5 /* 0...n */ - - /** - * Determine if the server's current MODULE_MAGIC_NUMBER is at least a -Index: httpd-2.2.4/configure.in -=================================================================== ---- httpd-2.2.4.orig/configure.in -+++ httpd-2.2.4/configure.in -@@ -392,6 +392,7 @@ initgroups \ - bindprocessor \ - prctl \ - timegm \ -+getpgid - ) - - dnl confirm that a void pointer is large enough to store a long integer -Index: httpd-2.2.4/server/mpm/experimental/itk/itk.c -=================================================================== ---- httpd-2.2.4.orig/server/mpm/experimental/itk/itk.c -+++ httpd-2.2.4/server/mpm/experimental/itk/itk.c -@@ -1199,7 +1199,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p - for (index = 0; index < ap_daemons_limit; ++index) { - if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) { - /* Ask each child to close its listeners. */ -- kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL); -+ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL); - active_children++; - } - } -@@ -1237,12 +1237,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p - - active_children = 0; - for (index = 0; index < ap_daemons_limit; ++index) { -- if (MPM_CHILD_PID(index) != 0) { -- if (kill(MPM_CHILD_PID(index), 0) == 0) { -- active_children = 1; -- /* Having just one child is enough to stay around */ -- break; -- } -+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) { -+ active_children = 1; -+ /* Having just one child is enough to stay around */ -+ break; - } - } - } while (!shutdown_pending && active_children && -@@ -1294,7 +1292,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_p - * piped loggers, etc. They almost certainly won't handle - * it gracefully. - */ -- kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); -+ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL); - } - } - } |