public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:32 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:32 UTC (permalink / raw
  To: gentoo-commits

commit:     7186abe3a1b57d548facc341c651efbde103e67e
Author:     Benedikt Boehm <hollow <AT> gentoo <DOT> org>
AuthorDate: Sat Oct 25 14:38:22 2008 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Sat Oct 25 14:38:22 2008 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=7186abe3

remove obsolete patches

---
 2.2/patches/10_all_CVE-2008-2939.patch | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/2.2/patches/10_all_CVE-2008-2939.patch b/2.2/patches/10_all_CVE-2008-2939.patch
deleted file mode 100644
index 7bf57c8..0000000
--- a/2.2/patches/10_all_CVE-2008-2939.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_ftp.c	2008/08/05 19:00:05	682869
-+++ httpd/httpd/branches/2.2.x/modules/proxy/mod_proxy_ftp.c	2008/08/05 19:01:50	682870
-@@ -383,6 +383,7 @@
-                                                            c->bucket_alloc));
-         }
-         if (wildcard != NULL) {
-+            wildcard = ap_escape_html(p, wildcard);
-             APR_BRIGADE_INSERT_TAIL(out, apr_bucket_pool_create(wildcard,
-                                                            strlen(wildcard), p,
-                                                            c->bucket_alloc));


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:32 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:32 UTC (permalink / raw
  To: gentoo-commits

commit:     26973886b3fa505f9497a2804165408fc2c3c7b6
Author:     Benedikt Boehm <hollow <AT> gentoo <DOT> org>
AuthorDate: Sat Oct 25 14:38:01 2008 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Sat Oct 25 14:38:01 2008 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=26973886

update itk patch

---
 2.2/patches/21_all_itk_20080105.patch | 234 +++++++++++++++++-----------------
 1 file changed, 114 insertions(+), 120 deletions(-)

diff --git a/2.2/patches/21_all_itk_20080105.patch b/2.2/patches/21_all_itk_20080105.patch
index bf498d7..a9580eb 100644
--- a/2.2/patches/21_all_itk_20080105.patch
+++ b/2.2/patches/21_all_itk_20080105.patch
@@ -1,49 +1,22 @@
-Index: httpd-2.2.8/server/mpm/config.m4
-===================================================================
---- httpd-2.2.8.orig/server/mpm/config.m4
-+++ httpd-2.2.8/server/mpm/config.m4
-@@ -1,7 +1,7 @@
- AC_MSG_CHECKING(which MPM to use)
- AC_ARG_WITH(mpm,
- APACHE_HELP_STRING(--with-mpm=MPM,Choose the process model for Apache to use.
--                          MPM={beos|event|worker|prefork|mpmt_os2|peruser}),[
-+                          MPM={beos|event|worker|prefork|mpmt_os2|peruser|itk}),[
-   APACHE_MPM=$withval
- ],[
-   if test "x$APACHE_MPM" = "x"; then
-@@ -23,7 +23,7 @@ ap_mpm_is_threaded ()
- 
- ap_mpm_is_experimental ()
- {
--    if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "peruser" ; then
-+    if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "peruser" -o "$apache_cv_mpm" = "itk" ; then
-         return 0
-     else
-         return 1
-@@ -66,6 +66,11 @@ if ap_mpm_is_experimental; then
- else
-   MPM_SUBDIR_NAME=$MPM_NAME
- fi
+unchanged:
+--- apache2.2/server/mpm/experimental/itk/Makefile.in
++++ apache2.2/server/mpm/experimental/itk/Makefile.in
+@@ -0,0 +1,5 @@
 +
-+if "$apache_cv_mpm" = "itk" ; then
-+  AC_CHECK_LIB(cap, cap_init)
-+fi
++LTLIBRARY_NAME    = libitk.la
++LTLIBRARY_SOURCES = itk.c
 +
- MPM_DIR=server/mpm/$MPM_SUBDIR_NAME
- MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la
- 
-Index: httpd-2.2.8/server/mpm/experimental/itk/config.m4
-===================================================================
---- /dev/null
-+++ httpd-2.2.8/server/mpm/experimental/itk/config.m4
++include $(top_srcdir)/build/ltlib.mk
+unchanged:
+--- apache2.2/server/mpm/experimental/itk/config.m4
++++ apache2.2/server/mpm/experimental/itk/config.m4	2007-01-29 21:03:57.000000000 +0100
 @@ -0,0 +1,3 @@
 +if test "$MPM_NAME" = "itk" ; then
 +    APACHE_FAST_OUTPUT(server/mpm/$MPM_SUBDIR_NAME/Makefile)
 +fi
-Index: httpd-2.2.8/server/mpm/experimental/itk/itk.c
-===================================================================
---- /dev/null
-+++ httpd-2.2.8/server/mpm/experimental/itk/itk.c
+diff -u apache2.2/server/mpm/experimental/itk/itk.c apache2.2/server/mpm/experimental/itk/itk.c
+--- apache2.2/server/mpm/experimental/itk/itk.c
++++ apache2.2/server/mpm/experimental/itk/itk.c
 @@ -0,0 +1,1704 @@
 +/* Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
@@ -1749,20 +1722,78 @@ Index: httpd-2.2.8/server/mpm/experimental/itk/itk.c
 +    itk_cmds,                   /* command apr_table_t */
 +    itk_hooks,                  /* register hooks */
 +};
-Index: httpd-2.2.8/server/mpm/experimental/itk/Makefile.in
-===================================================================
---- /dev/null
-+++ httpd-2.2.8/server/mpm/experimental/itk/Makefile.in
-@@ -0,0 +1,5 @@
+unchanged:
+--- apache2.2/server/mpm/experimental/itk/mpm.h
++++ apache2.2/server/mpm/experimental/itk/mpm.h	2007-01-29 21:22:33.000000000 +0100
+@@ -0,0 +1,65 @@
++/* Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ *
++ * Portions copyright 2005-2007 Steinar H. Gunderson <sgunderson@bigfoot.com>.
++ * Licensed under the same terms as the rest of Apache.
++ */
 +
-+LTLIBRARY_NAME    = libitk.la
-+LTLIBRARY_SOURCES = itk.c
++/**
++ * @file itk/mpm.h
++ * @brief ITK MPM (setuid per-vhost, no threads)
++ *
++ * @defgroup APACHE_MPM_ITK Apache ITK
++ * @ingroup  APACHE_MPM APACHE_OS_UNIX
++ * @{
++ */
 +
-+include $(top_srcdir)/build/ltlib.mk
-Index: httpd-2.2.8/server/mpm/experimental/itk/mpm_default.h
-===================================================================
---- /dev/null
-+++ httpd-2.2.8/server/mpm/experimental/itk/mpm_default.h
++#include "httpd.h"
++#include "mpm_default.h"
++#include "scoreboard.h"
++#include "unixd.h"
++
++#ifndef APACHE_MPM_ITK_H
++#define APACHE_MPM_ITK_H
++
++#define ITK_MPM
++
++#define MPM_NAME "ITK"
++
++#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
++#define AP_MPM_WANT_WAIT_OR_TIMEOUT
++#define AP_MPM_WANT_PROCESS_CHILD_STATUS
++#define AP_MPM_WANT_SET_PIDFILE
++#define AP_MPM_WANT_SET_SCOREBOARD
++#define AP_MPM_WANT_SET_LOCKFILE
++#define AP_MPM_WANT_SET_MAX_REQUESTS
++#define AP_MPM_WANT_SET_COREDUMPDIR
++#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
++#define AP_MPM_WANT_SIGNAL_SERVER
++#define AP_MPM_WANT_SET_MAX_MEM_FREE
++#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER
++#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN
++#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
++
++#define AP_MPM_USES_POD 1
++#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
++#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
++#define MPM_ACCEPT_FUNC unixd_accept
++
++extern int ap_threads_per_child;
++extern int ap_max_daemons_limit;
++extern server_rec *ap_server_conf;
++#endif /* APACHE_MPM_ITK_H */
++/** @} */
+unchanged:
+--- apache2.2/server/mpm/experimental/itk/mpm_default.h
++++ apache2.2/server/mpm/experimental/itk/mpm_default.h	2007-01-29 21:22:09.000000000 +0100
 @@ -0,0 +1,77 @@
 +/* Licensed to the Apache Software Foundation (ASF) under one or more
 + * contributor license agreements.  See the NOTICE file distributed with
@@ -1841,73 +1872,36 @@ Index: httpd-2.2.8/server/mpm/experimental/itk/mpm_default.h
 +
 +#endif /* AP_MPM_DEFAULT_H */
 +/** @} */
-Index: httpd-2.2.8/server/mpm/experimental/itk/mpm.h
-===================================================================
---- /dev/null
-+++ httpd-2.2.8/server/mpm/experimental/itk/mpm.h
-@@ -0,0 +1,65 @@
-+/* Licensed to the Apache Software Foundation (ASF) under one or more
-+ * contributor license agreements.  See the NOTICE file distributed with
-+ * this work for additional information regarding copyright ownership.
-+ * The ASF licenses this file to You under the Apache License, Version 2.0
-+ * (the "License"); you may not use this file except in compliance with
-+ * the License.  You may obtain a copy of the License at
-+ *
-+ *     http://www.apache.org/licenses/LICENSE-2.0
-+ *
-+ * Unless required by applicable law or agreed to in writing, software
-+ * distributed under the License is distributed on an "AS IS" BASIS,
-+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ * See the License for the specific language governing permissions and
-+ * limitations under the License.
-+ *
-+ * Portions copyright 2005-2007 Steinar H. Gunderson <sgunderson@bigfoot.com>.
-+ * Licensed under the same terms as the rest of Apache.
-+ */
-+
-+/**
-+ * @file itk/mpm.h
-+ * @brief ITK MPM (setuid per-vhost, no threads)
-+ *
-+ * @defgroup APACHE_MPM_ITK Apache ITK
-+ * @ingroup  APACHE_MPM APACHE_OS_UNIX
-+ * @{
-+ */
-+
-+#include "httpd.h"
-+#include "mpm_default.h"
-+#include "scoreboard.h"
-+#include "unixd.h"
-+
-+#ifndef APACHE_MPM_ITK_H
-+#define APACHE_MPM_ITK_H
-+
-+#define ITK_MPM
-+
-+#define MPM_NAME "ITK"
-+
-+#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
-+#define AP_MPM_WANT_WAIT_OR_TIMEOUT
-+#define AP_MPM_WANT_PROCESS_CHILD_STATUS
-+#define AP_MPM_WANT_SET_PIDFILE
-+#define AP_MPM_WANT_SET_SCOREBOARD
-+#define AP_MPM_WANT_SET_LOCKFILE
-+#define AP_MPM_WANT_SET_MAX_REQUESTS
-+#define AP_MPM_WANT_SET_COREDUMPDIR
-+#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
-+#define AP_MPM_WANT_SIGNAL_SERVER
-+#define AP_MPM_WANT_SET_MAX_MEM_FREE
-+#define AP_MPM_WANT_FATAL_SIGNAL_HANDLER
-+#define AP_MPM_WANT_SET_GRACEFUL_SHUTDOWN
-+#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
+unchanged:
+--- apache2.2/server/mpm/config.m4	2007-01-29 21:30:35.000000000 +0100
++++ apache2.2/server/mpm/config.m4
+@@ -1,7 +1,7 @@
+ AC_MSG_CHECKING(which MPM to use)
+ AC_ARG_WITH(mpm,
+ APACHE_HELP_STRING(--with-mpm=MPM,Choose the process model for Apache to use.
+-                          MPM={beos|event|worker|prefork|mpmt_os2|peruser}),[
++                          MPM={beos|event|worker|prefork|mpmt_os2|peruser|itk}),[
+   APACHE_MPM=$withval
+ ],[
+   if test "x$APACHE_MPM" = "x"; then
+@@ -23,7 +23,7 @@
+ 
+ ap_mpm_is_experimental ()
+ {
+-    if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "peruser" ; then
++    if test "$apache_cv_mpm" = "event" -o "$apache_cv_mpm" = "peruser" -o "$apache_cv_mpm" = "itk" ; then
+         return 0
+     else
+         return 1
+@@ -66,6 +66,11 @@
+ else
+   MPM_SUBDIR_NAME=$MPM_NAME
+ fi
 +
-+#define AP_MPM_USES_POD 1
-+#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-+#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-+#define MPM_ACCEPT_FUNC unixd_accept
++if test "$apache_cv_mpm" = "itk" ; then
++  AC_CHECK_LIB(cap, cap_init)
++fi
 +
-+extern int ap_threads_per_child;
-+extern int ap_max_daemons_limit;
-+extern server_rec *ap_server_conf;
-+#endif /* APACHE_MPM_ITK_H */
-+/** @} */
+ MPM_DIR=server/mpm/$MPM_SUBDIR_NAME
+ MPM_LIB=$MPM_DIR/lib${MPM_NAME}.la
+ 


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:32 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:32 UTC (permalink / raw
  To: gentoo-commits

commit:     f0838f01e55b706bb9314859a7a51dd565f415e7
Author:     Benedikt Boehm <hollow <AT> gentoo <DOT> org>
AuthorDate: Thu Jan  1 13:50:09 2009 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Thu Jan  1 13:50:09 2009 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=f0838f01

bump sni patch, #252363

---
 2.2/patches/04_all_mod_ssl_tls_sni.patch | 98 +++++++++++++++++++++++++-------
 1 file changed, 77 insertions(+), 21 deletions(-)

diff --git a/2.2/patches/04_all_mod_ssl_tls_sni.patch b/2.2/patches/04_all_mod_ssl_tls_sni.patch
index 6e5b86c..73392ae 100644
--- a/2.2/patches/04_all_mod_ssl_tls_sni.patch
+++ b/2.2/patches/04_all_mod_ssl_tls_sni.patch
@@ -9,10 +9,10 @@
 # must be configured explicitly for TLS extension support at compile time
 # ("./config enable-tlsext").
 
-Index: httpd-2.2.8/modules/ssl/ssl_private.h
+Index: httpd-2.2.x/modules/ssl/ssl_private.h
 ===================================================================
---- httpd-2.2.8.orig/modules/ssl/ssl_private.h
-+++ httpd-2.2.8/modules/ssl/ssl_private.h
+--- httpd-2.2.x/modules/ssl/ssl_private.h	(revision 663014)
++++ httpd-2.2.x/modules/ssl/ssl_private.h	(working copy)
 @@ -35,6 +35,7 @@
  #include "http_connection.h"
  #include "http_request.h"
@@ -31,10 +31,10 @@ Index: httpd-2.2.8/modules/ssl/ssl_private.h
  
  /**  Session Cache Support  */
  void         ssl_scache_init(server_rec *, apr_pool_t *);
-Index: httpd-2.2.8/modules/ssl/ssl_engine_init.c
+Index: httpd-2.2.x/modules/ssl/ssl_engine_init.c
 ===================================================================
---- httpd-2.2.8.orig/modules/ssl/ssl_engine_init.c
-+++ httpd-2.2.8/modules/ssl/ssl_engine_init.c
+--- httpd-2.2.x/modules/ssl/ssl_engine_init.c	(revision 663014)
++++ httpd-2.2.x/modules/ssl/ssl_engine_init.c	(working copy)
 @@ -355,6 +355,33 @@ static void ssl_init_server_check(server
      }
  }
@@ -79,9 +79,18 @@ Index: httpd-2.2.8/modules/ssl/ssl_engine_init.c
      }
  }
  
-@@ -1038,7 +1068,11 @@ void ssl_init_CheckServers(server_rec *b
+@@ -1036,9 +1066,19 @@ void ssl_init_CheckServers(server_rec *b
+         klen = strlen(key);
+ 
          if ((ps = (server_rec *)apr_hash_get(table, key, klen))) {
-             ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
+-            ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
++            ap_log_error(APLOG_MARK, 
++#ifdef OPENSSL_NO_TLSEXT
++                         APLOG_WARNING, 
++#else
++                         APLOG_DEBUG, 
++#endif
++                         0,
                           base_server,
 +#ifdef OPENSSL_NO_TLSEXT
                           "Init: SSL server IP/port conflict: "
@@ -91,7 +100,7 @@ Index: httpd-2.2.8/modules/ssl/ssl_engine_init.c
                           "%s (%s:%d) vs. %s (%s:%d)",
                           ssl_util_vhostid(p, s),
                           (s->defn_name ? s->defn_name : "unknown"),
-@@ -1055,8 +1089,14 @@ void ssl_init_CheckServers(server_rec *b
+@@ -1055,8 +1095,14 @@ void ssl_init_CheckServers(server_rec *b
  
      if (conflict) {
          ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server,
@@ -106,10 +115,10 @@ Index: httpd-2.2.8/modules/ssl/ssl_engine_init.c
      }
  }
  
-Index: httpd-2.2.8/modules/ssl/ssl_engine_vars.c
+Index: httpd-2.2.x/modules/ssl/ssl_engine_vars.c
 ===================================================================
---- httpd-2.2.8.orig/modules/ssl/ssl_engine_vars.c
-+++ httpd-2.2.8/modules/ssl/ssl_engine_vars.c
+--- httpd-2.2.x/modules/ssl/ssl_engine_vars.c	(revision 663014)
++++ httpd-2.2.x/modules/ssl/ssl_engine_vars.c	(working copy)
 @@ -320,6 +320,12 @@ static char *ssl_var_lookup_ssl(apr_pool
      else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
          result = ssl_var_lookup_ssl_compress_meth(ssl);
@@ -123,10 +132,10 @@ Index: httpd-2.2.8/modules/ssl/ssl_engine_vars.c
      return result;
  }
  
-Index: httpd-2.2.8/modules/ssl/ssl_engine_kernel.c
+Index: httpd-2.2.x/modules/ssl/ssl_engine_kernel.c
 ===================================================================
---- httpd-2.2.8.orig/modules/ssl/ssl_engine_kernel.c
-+++ httpd-2.2.8/modules/ssl/ssl_engine_kernel.c
+--- httpd-2.2.x/modules/ssl/ssl_engine_kernel.c	(revision 663014)
++++ httpd-2.2.x/modules/ssl/ssl_engine_kernel.c	(working copy)
 @@ -31,6 +31,9 @@
  #include "ssl_private.h"
  
@@ -162,7 +171,31 @@ Index: httpd-2.2.8/modules/ssl/ssl_engine_kernel.c
      SSL_set_app_data2(ssl, r);
  
      /*
-@@ -997,6 +1011,9 @@ int ssl_hook_Fixup(request_rec *r)
+@@ -353,6 +367,11 @@ int ssl_hook_Access(request_rec *r)
+      * currently active/remembered verify depth (because this means more
+      * restriction on the certificate chain).
+      */
++    if ((sc->server->auth.verify_depth != UNSET) &&
++        (dc->nVerifyDepth == UNSET)) {
++        /* apply per-vhost setting, if per-directory config is not set */
++        dc->nVerifyDepth = sc->server->auth.verify_depth;
++    }
+     if (dc->nVerifyDepth != UNSET) {
+         /* XXX: doesnt look like sslconn->verify_depth is actually used */
+         if (!(n = sslconn->verify_depth)) {
+@@ -382,6 +401,11 @@ int ssl_hook_Access(request_rec *r)
+      * verification but at least skip the I/O-intensive renegotation
+      * handshake.
+      */
++    if ((sc->server->auth.verify_mode != SSL_CVERIFY_UNSET) &&
++        (dc->nVerifyClient == SSL_CVERIFY_UNSET)) {
++        /* apply per-vhost setting, if per-directory config is not set */
++        dc->nVerifyClient = sc->server->auth.verify_mode;
++    }
+     if (dc->nVerifyClient != SSL_CVERIFY_UNSET) {
+         /* remember old state */
+         verify_old = SSL_get_verify_mode(ssl);
+@@ -997,6 +1021,9 @@ int ssl_hook_Fixup(request_rec *r)
      SSLDirConfigRec *dc = myDirConfig(r);
      apr_table_t *env = r->subprocess_env;
      char *var, *val = "";
@@ -172,7 +205,7 @@ Index: httpd-2.2.8/modules/ssl/ssl_engine_kernel.c
      STACK_OF(X509) *peer_certs;
      SSL *ssl;
      int i;
-@@ -1018,6 +1035,13 @@ int ssl_hook_Fixup(request_rec *r)
+@@ -1018,6 +1045,13 @@ int ssl_hook_Fixup(request_rec *r)
      /* the always present HTTPS (=HTTP over SSL) flag! */
      apr_table_setn(env, "HTTPS", "on");
  
@@ -186,7 +219,7 @@ Index: httpd-2.2.8/modules/ssl/ssl_engine_kernel.c
      /* standard SSL environment variables */
      if (dc->nOptions & SSL_OPT_STDENVVARS) {
          for (i = 0; ssl_hook_Fixup_vars[i]; i++) {
-@@ -1810,3 +1834,118 @@ void ssl_callback_LogTracingState(MODSSL
+@@ -1810,3 +1844,141 @@ void ssl_callback_LogTracingState(MODSSL
      }
  }
  
@@ -299,16 +332,39 @@ Index: httpd-2.2.8/modules/ssl/ssl_engine_kernel.c
 +                           SSL_CTX_get_verify_callback(ssl->ctx));
 +        }
 +
++        /*
++         * We also need to make sure that the correct mctx
++         * (accessed through the c->base_server->module_config vector)
++         * is assigned to the connection - the CRL callback e.g.
++         * makes use of it for retrieving its store (mctx->crl).
++         * Since logging in callbacks uses c->base_server in many
++         * cases, it also ensures that these messages are routed
++         * to the proper log.
++         */
++        c->base_server = s;
++
++        /*
++         * There is one special filter callback, which is set
++         * very early depending on the base_server's log level.
++         * If this is not the first vhost we're now selecting
++         * (and the first vhost doesn't use APLOG_DEBUG), then
++         * we need to set that callback here.
++         */
++        if (c->base_server->loglevel >= APLOG_DEBUG) {
++            BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
++            BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl);
++        }
++
 +        return 1;
 +    }
 +
 +    return 0;
 +}
 +#endif
-Index: httpd-2.2.8/modules/ssl/ssl_toolkit_compat.h
+Index: httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h
 ===================================================================
---- httpd-2.2.8.orig/modules/ssl/ssl_toolkit_compat.h
-+++ httpd-2.2.8/modules/ssl/ssl_toolkit_compat.h
+--- httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h	(revision 663014)
++++ httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h	(working copy)
 @@ -264,6 +264,12 @@ typedef void (*modssl_popfree_fn)(char *
  #define SSL_SESS_CACHE_NO_INTERNAL  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
  #endif


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:32 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:32 UTC (permalink / raw
  To: gentoo-commits

commit:     76724def1d1cd41c8aefd048687b16efcb5da9f4
Author:     Benedikt Boehm <hollow <AT> gentoo <DOT> org>
AuthorDate: Tue Jul  7 09:55:10 2009 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Tue Jul  7 09:55:10 2009 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=76724def

add more patches

---
 2.2/patches/09_all_CVE-2009-1891.patch | 29 +++++++++++++++
 2.2/patches/10_all_r779472.patch       | 67 ++++++++++++++++++++++++++++++++++
 2.2/patches/11_all_r790738.patch       | 18 +++++++++
 3 files changed, 114 insertions(+)

diff --git a/2.2/patches/09_all_CVE-2009-1891.patch b/2.2/patches/09_all_CVE-2009-1891.patch
new file mode 100644
index 0000000..4d778f8
--- /dev/null
+++ b/2.2/patches/09_all_CVE-2009-1891.patch
@@ -0,0 +1,29 @@
+--- httpd/httpd/branches/2.2.x/server/core_filters.c	2009/07/06 12:01:05	791453
++++ httpd/httpd/branches/2.2.x/server/core_filters.c	2009/07/06 12:03:20	791454
+@@ -542,6 +542,12 @@
+     apr_read_type_e eblock = APR_NONBLOCK_READ;
+     apr_pool_t *input_pool = b->p;
+ 
++    /* Fail quickly if the connection has already been aborted. */
++    if (c->aborted) {
++        apr_brigade_cleanup(b);
++        return APR_ECONNABORTED;
++    }
++
+     if (ctx == NULL) {
+         ctx = apr_pcalloc(c->pool, sizeof(*ctx));
+         net->out_ctx = ctx;
+@@ -909,12 +915,9 @@
+             /* No need to check for SUCCESS, we did that above. */
+             if (!APR_STATUS_IS_EAGAIN(rv)) {
+                 c->aborted = 1;
++                return APR_ECONNABORTED;
+             }
+ 
+-            /* The client has aborted, but the request was successful. We
+-             * will report success, and leave it to the access and error
+-             * logs to note that the connection was aborted.
+-             */
+             return APR_SUCCESS;
+         }
+ 

diff --git a/2.2/patches/10_all_r779472.patch b/2.2/patches/10_all_r779472.patch
new file mode 100644
index 0000000..c4bb6cb
--- /dev/null
+++ b/2.2/patches/10_all_r779472.patch
@@ -0,0 +1,67 @@
+Index: server/core.c
+===================================================================
+--- server/core.c	(revision 779471)
++++ server/core.c	(revision 779472)
+@@ -661,7 +661,11 @@
+     core_dir_config *conf =
+       (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+ 
+-    return conf->opts;
++    /* Per comment in http_core.h - the OPT_INC_WITH_EXEC bit is
++     * inverted, such that the exposed semantics match that of
++     * OPT_INCNOEXEC; i.e., the bit is only enabled if exec= is *not*
++     * permitted. */
++    return conf->opts ^ OPT_INC_WITH_EXEC;
+ }
+ 
+ AP_DECLARE(int) ap_allow_overrides(request_rec *r)
+Index: modules/filters/mod_include.c
+===================================================================
+--- modules/filters/mod_include.c	(revision 779471)
++++ modules/filters/mod_include.c	(revision 779472)
+@@ -3565,7 +3565,7 @@
+         intern->seen_eos = 0;
+         intern->state = PARSE_PRE_HEAD;
+         ctx->flags = (SSI_FLAG_PRINTING | SSI_FLAG_COND_TRUE);
+-        if ((ap_allow_options(r) & OPT_INC_WITH_EXEC) == 0) {
++        if (ap_allow_options(r) & OPT_INCNOEXEC) {
+             ctx->flags |= SSI_FLAG_NO_EXEC;
+         }
+         intern->accessenable = conf->accessenable;
+Index: include/http_core.h
+===================================================================
+--- include/http_core.h	(revision 779471)
++++ include/http_core.h	(revision 779472)
+@@ -73,16 +73,29 @@
+ #define OPT_EXECCGI 8
+ /**  directive unset */
+ #define OPT_UNSET 16
+-/**  SSI exec= permission is permitted, iff OPT_INCLUDES is also set */
+-#define OPT_INC_WITH_EXEC 32
++/**  IncludesNOEXEC directive */
++#define OPT_INCNOEXEC 32
+ /** SymLinksIfOwnerMatch directive */
+ #define OPT_SYM_OWNER 64
+ /** MultiViews directive */
+ #define OPT_MULTI 128
+ /**  All directives */
+-#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_INC_WITH_EXEC|OPT_SYM_LINKS|OPT_EXECCGI)
++#define OPT_ALL (OPT_INDEXES|OPT_INCLUDES|OPT_INCNOEXEC|OPT_SYM_LINKS|OPT_EXECCGI)
+ /** @} */
+ 
++#ifdef CORE_PRIVATE
++/* For internal use only - since 2.2.12, the OPT_INCNOEXEC bit is
++ * internally replaced by OPT_INC_WITH_EXEC.  The internal semantics
++ * of the two SSI-related bits are hence:
++ *
++ *  OPT_INCLUDES => "enable SSI, without exec= permission"
++ *  OPT_INC_WITH_EXEC => "iff OPT_INCLUDES is set, also enable exec="
++ *
++ * The set of options exposed via ap_allow_options() retains the
++ * semantics of OPT_INCNOEXEC by flipping the bit. */
++#define OPT_INC_WITH_EXEC OPT_INCNOEXEC
++#endif
++
+ /**
+  * @defgroup get_remote_host Remote Host Resolution 
+  * @ingroup APACHE_CORE_HTTPD

diff --git a/2.2/patches/11_all_r790738.patch b/2.2/patches/11_all_r790738.patch
new file mode 100644
index 0000000..3ddf33b
--- /dev/null
+++ b/2.2/patches/11_all_r790738.patch
@@ -0,0 +1,18 @@
+Index: server/core.c
+===================================================================
+--- server/core.c	(revision 790737)
++++ server/core.c	(revision 790738)
+@@ -665,7 +665,12 @@
+      * inverted, such that the exposed semantics match that of
+      * OPT_INCNOEXEC; i.e., the bit is only enabled if exec= is *not*
+      * permitted. */
+-    return conf->opts ^ OPT_INC_WITH_EXEC;
++    if (conf->opts & OPT_INCLUDES) {
++        return conf->opts ^ OPT_INC_WITH_EXEC;
++    }
++    else {
++        return conf->opts;
++    }
+ }
+ 
+ AP_DECLARE(int) ap_allow_overrides(request_rec *r)


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:32 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:32 UTC (permalink / raw
  To: gentoo-commits

commit:     402d97e18378ff8008fa4eadcad9684a8397401d
Author:     Benedikt Boehm <hollow <AT> gentoo <DOT> org>
AuthorDate: Thu Jan  1 13:50:31 2009 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Thu Jan  1 13:50:31 2009 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=402d97e1

update itk patch, remove obsolete libtool patch

---
 2.2/patches/02_all_libtool22.patch                          | 13 -------------
 ...{21_all_itk_20080105.patch => 21_all_itk_20080727.patch} |  0
 2 files changed, 13 deletions(-)

diff --git a/2.2/patches/02_all_libtool22.patch b/2.2/patches/02_all_libtool22.patch
deleted file mode 100644
index 69f1a21..0000000
--- a/2.2/patches/02_all_libtool22.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-Index: configure.in
-===================================================================
---- configure.in	(revision 647627)
-+++ configure.in	(working copy)
-@@ -237,7 +237,7 @@
-       LIBTOOL="$my_libtool \$(LTFLAGS)"
-       libtoolversion=`$my_libtool --version`
-       case $libtoolversion in
--          *1.[[45]]*)
-+          *1.[[45]]* | *[[2-9]].[[0-9]]*)
-               SH_LIBTOOL='$(LIBTOOL)'
-               SHLTCFLAGS="-prefer-pic"
-               LTCFLAGS="-prefer-non-pic -static"

diff --git a/2.2/patches/21_all_itk_20080105.patch b/2.2/patches/21_all_itk_20080727.patch
similarity index 100%
rename from 2.2/patches/21_all_itk_20080105.patch
rename to 2.2/patches/21_all_itk_20080727.patch


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:32 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:32 UTC (permalink / raw
  To: gentoo-commits

commit:     4a864892957948b8fd4845fa082ceefd9677fe8c
Author:     Benedikt Boehm <hollow <AT> gentoo <DOT> org>
AuthorDate: Fri Jul 24 18:35:44 2009 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Fri Jul 24 18:35:44 2009 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=4a864892

add peruser-dc patch

---
 2.2/patches/22_all_peruser_0.3.0-dc3.patch | 1211 ++++++++++++++++++++++++++++
 1 file changed, 1211 insertions(+)

diff --git a/2.2/patches/22_all_peruser_0.3.0-dc3.patch b/2.2/patches/22_all_peruser_0.3.0-dc3.patch
new file mode 100644
index 0000000..9bb7d17
--- /dev/null
+++ b/2.2/patches/22_all_peruser_0.3.0-dc3.patch
@@ -0,0 +1,1211 @@
+--- httpd-2.2.3/server/mpm/experimental/peruser/mpm_default.h	2009-05-27 15:09:19.000000000 +0300
++++ httpd-2.2.3-dc/server/mpm/experimental/peruser/mpm_default.h	2009-05-28 10:10:42.000000000 +0300
+@@ -77,6 +77,12 @@
+ #define DEFAULT_MIN_FREE_PROCESSORS 2
+ #endif
+ 
++/* Maximum --- more than this, and idle processors will be killed (0 = disable) */
++
++#ifndef DEFAULT_MAX_FREE_PROCESSORS
++#define DEFAULT_MAX_FREE_PROCESSORS 0
++#endif
++
+ /* Maximum processors per ServerEnvironment */
+ 
+ #ifndef DEFAULT_MAX_PROCESSORS
+@@ -107,4 +113,50 @@
+ #define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
+ #endif
+ 
++/* Maximum multiplexers */
++
++#ifndef DEFAULT_MAX_MULTIPLEXERS
++#define DEFAULT_MAX_MULTIPLEXERS 20
++#endif
++
++/* Minimum multiplexers */
++
++#ifndef DEFAULT_MIN_MULTIPLEXERS
++#define DEFAULT_MIN_MULTIPLEXERS 3
++#endif
++
++/* Amount of time a child can run before it expires (0 = turn off) */
++
++#ifndef DEFAULT_EXPIRE_TIMEOUT
++#define DEFAULT_EXPIRE_TIMEOUT 1800
++#endif
++
++/* Amount of time a child can stay idle (0 = turn off) */
++
++#ifndef DEFAULT_IDLE_TIMEOUT
++#define DEFAULT_IDLE_TIMEOUT 900
++#endif
++
++/* Amount of time a multiplexer can stay idle (0 = turn off) */
++
++#ifndef DEFAULT_MULTIPLEXER_IDLE_TIMEOUT
++#define DEFAULT_MULTIPLEXER_IDLE_TIMEOUT 0
++#endif
++
++/* Amount of maximum time a multiplexer can wait for processor if it is busy (0 = never wait)
++ * This is decreased with every busy request
++ */
++
++#ifndef DEFAULT_PROCESSOR_WAIT_TIMEOUT
++#define DEFAULT_PROCESSOR_WAIT_TIMEOUT 5
++#endif
++
++/* The number of different levels there are when a multiplexer is waiting for processor
++ * (between maximum waiting time and no waiting)
++ */
++
++#ifndef DEFAULT_PROCESSOR_WAIT_STEPS
++#define DEFAULT_PROCESSOR_WAIT_STEPS 10
++#endif
++
+ #endif /* AP_MPM_DEFAULT_H */
+--- httpd-2.2.3/server/mpm/experimental/peruser/mpm.h	2009-03-22 22:46:45.000000000 +0200
++++ httpd-2.2.3-dc/server/mpm/experimental/peruser/mpm.h	2009-03-22 22:39:10.000000000 +0200
+@@ -84,6 +84,7 @@
+ #define AP_MPM_USES_POD 1
+ #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
+ #define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
++#define MPM_VALID_PID(p) (getpgid(p) == getpgrp())
+ #define MPM_ACCEPT_FUNC unixd_accept
+ 
+ extern int ap_threads_per_child;
+--- httpd-2.2.3/server/mpm/experimental/peruser/peruser.c	2009-05-27 15:09:19.000000000 +0300
++++ httpd-2.2.3-dc/server/mpm/experimental/peruser/peruser.c	2009-05-28 13:54:27.000000000 +0300
+@@ -195,20 +195,30 @@
+ 
+ #define CHILD_STATUS_STANDBY  0  /* wait for a request before starting */
+ #define CHILD_STATUS_STARTING 1  /* wait for socket creation */
+-#define CHILD_STATUS_READY    2  /* wait for mux to restart */
+-#define CHILD_STATUS_ACTIVE   3  /* ready to take requests */
++#define CHILD_STATUS_READY    2  /* is ready to take requests */
++#define CHILD_STATUS_ACTIVE   3  /* is currently busy handling requests */
+ #define CHILD_STATUS_RESTART  4  /* child about to die and restart */
+ 
++/* cgroup settings */
++#define CGROUP_TASKS_FILE "/tasks"
++#define CGROUP_TASKS_FILE_LEN 7
++
+ /* config globals */
+ 
+ int ap_threads_per_child=0;         /* Worker threads per child */
+ static apr_proc_mutex_t *accept_mutex;
+ static int ap_min_processors=DEFAULT_MIN_PROCESSORS;
+ static int ap_min_free_processors=DEFAULT_MIN_FREE_PROCESSORS;
++static int ap_max_free_processors=DEFAULT_MAX_FREE_PROCESSORS;
+ static int ap_max_processors=DEFAULT_MAX_PROCESSORS;
++static int ap_min_multiplexers=DEFAULT_MIN_MULTIPLEXERS;
++static int ap_max_multiplexers=DEFAULT_MAX_MULTIPLEXERS;
+ static int ap_daemons_limit=0;      /* MaxClients */
+-static int expire_timeout=1800;
+-static int idle_timeout=900;
++static int expire_timeout=DEFAULT_EXPIRE_TIMEOUT;
++static int idle_timeout=DEFAULT_IDLE_TIMEOUT;
++static int multiplexer_idle_timeout=DEFAULT_MULTIPLEXER_IDLE_TIMEOUT;
++static int processor_wait_timeout=DEFAULT_PROCESSOR_WAIT_TIMEOUT;
++static int processor_wait_steps=DEFAULT_PROCESSOR_WAIT_STEPS;
+ static int server_limit = DEFAULT_SERVER_LIMIT;
+ static int first_server_limit;
+ static int changed_limit_at_restart;
+@@ -222,15 +232,21 @@
+ {
+     int processor_id;
+ 
++    const char *name;	/* Server environment's unique string identifier */
++
+     /* security settings */
+     uid_t uid;          /* user id */
+     gid_t gid;          /* group id */
+     const char *chroot; /* directory to chroot() to, can be null */
++    int nice_lvl;
++    const char *cgroup; /* cgroup directory, can be null */
+ 
+     /* resource settings */
+     int min_processors;
+     int min_free_processors;
++    int max_free_processors;
+     int max_processors;
++    int availability;
+ 
+     /* sockets */
+     int input;          /* The socket descriptor */
+@@ -437,6 +453,25 @@
+     return "UNKNOWN";
+ }
+ 
++char* scoreboard_status_string(int status) {
++    switch(status)
++    {
++        case SERVER_DEAD:  return "DEAD";
++        case SERVER_STARTING: return "STARTING";
++        case SERVER_READY:    return "READY";
++        case SERVER_BUSY_READ:   return "BUSY_READ";
++        case SERVER_BUSY_WRITE:   return "BUSY_WRITE";
++        case SERVER_BUSY_KEEPALIVE:   return "BUSY_KEEPALIVE";
++        case SERVER_BUSY_LOG:   return "BUSY_LOG";
++        case SERVER_BUSY_DNS:   return "BUSY_DNS";
++        case SERVER_CLOSING:   return "CLOSING";
++        case SERVER_GRACEFUL:   return "GRACEFUL";
++        case SERVER_NUM_STATUS:   return "NUM_STATUS";
++    }
++
++    return "UNKNOWN";
++}
++
+ void dump_child_table()
+ {
+ #ifdef MPM_PERUSER_DEBUG
+@@ -511,10 +546,6 @@
+ 
+ static void accept_mutex_on(void)
+ {
+-/* for some reason this fails if we listen on the pipe_of_death.
+-   fortunately I don't think we currently need it */
+-
+-#if 0
+     apr_status_t rv = apr_proc_mutex_lock(accept_mutex);
+     if (rv != APR_SUCCESS) {
+         const char *msg = "couldn't grab the accept mutex";
+@@ -529,12 +560,10 @@
+             exit(APEXIT_CHILDFATAL);
+         }
+     }
+-#endif
+ }
+ 
+ static void accept_mutex_off(void)
+ {
+-#if 0
+     apr_status_t rv = apr_proc_mutex_unlock(accept_mutex);
+     if (rv != APR_SUCCESS) {
+         const char *msg = "couldn't release the accept mutex";
+@@ -552,7 +581,6 @@
+             exit(APEXIT_CHILDFATAL);
+         }
+     }
+-#endif
+ }
+ 
+ /* On some architectures it's safe to do unserialized accept()s in the single
+@@ -715,8 +743,10 @@
+     ret = apr_socket_recv(lr->sd, &pipe_read_char, &n);
+     if (APR_STATUS_IS_EAGAIN(ret))
+     {
+-            /* It lost the lottery. It must continue to suffer
+-             * through a life of servitude. */
++       /* It lost the lottery. It must continue to suffer
++        * through a life of servitude. */
++       _DBG("POD read EAGAIN");
++       return ret;
+     }
+     else
+     {
+@@ -1087,8 +1117,7 @@
+     for(i = 0, total = 0; i < NUM_CHILDS; ++i)
+     {
+         if(CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv &&
+-           (SCOREBOARD_STATUS(i) == SERVER_STARTING ||
+-            SCOREBOARD_STATUS(i) == SERVER_READY))
++           (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY))
+         {
+             total++;
+         }
+@@ -1116,7 +1145,7 @@
+     apr_bucket *bucket;
+     const apr_array_header_t *headers_in_array;
+     const apr_table_entry_t *headers_in;
+-    int counter;
++    int counter, wait_time, wait_step_size;
+ 
+     apr_socket_t *thesock = ap_get_module_config(r->connection->conn_config, &core_module);
+ 
+@@ -1137,10 +1166,73 @@
+       apr_table_get(r->headers_in, "Host"), my_child_num, processor->senv->output);
+     _DBG("r->the_request=\"%s\" len=%d", r->the_request, strlen(r->the_request));
+ 
+-    ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len);
++    wait_step_size = 100 / processor_wait_steps;
+ 
+-    /* Scan the brigade looking for heap-buckets */
++    /*	Check if the processor is available */
++    if (total_processors(processor->id) == processor->senv->max_processors &&
++        idle_processors(processor->id) == 0) {
++        /* The processor is currently busy, try to wait (a little) */
++        _DBG("processor seems to be busy, trying to wait for it");
++
++        if (processor->senv->availability == 0) {
++            processor->senv->availability = 0;
++
++            _DBG("processor is very busy (availability = 0) - not passing request");
++
++            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
++                         "Too many requests for processor %s, increase MaxProcessors", processor->senv->name);
++	    
++            /* No point in waiting for the processor, it's very busy */
++            return -1;
++        }
++        
++        /* We sleep a little (depending how available the processor usually is) */
++        int i;
++        
++        wait_time = (processor_wait_timeout / processor_wait_steps) * 1000000;
++
++        for(i = 0; i <= processor->senv->availability; i += wait_step_size) {
++            usleep(wait_time);
+ 
++            /* Check if the processor is ready */
++            if (total_processors(processor->id) < processor->senv->max_processors ||
++                idle_processors(processor->id) > 0) {
++                /* The processor has freed - lets use it */
++                _DBG("processor freed before wait time expired");
++                break;
++            }
++        }
++        
++        if (processor->senv->availability <= wait_step_size) {
++            processor->senv->availability = 0;
++        }
++        else processor->senv->availability -= wait_step_size;
++        
++        /* Check if we waited all the time */
++        if (i > processor->senv->availability) {
++            _DBG("processor is busy - not passing request (availability = %d)",
++                 processor->senv->availability);
++            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
++                         "Too many requests for processor %s, increase MaxProcessors", processor->senv->name);
++            return -1;
++        }
++
++        /* We could increase the availability a little here,
++         * because the processor got freed eventually
++         */
++    }
++    else {
++        /* Smoothly increment the availability back to 100 */
++        if (processor->senv->availability >= 100-wait_step_size) {
++            processor->senv->availability = 100;
++        }
++        else processor->senv->availability += wait_step_size;
++    }
++    
++    ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len);
++    
++    /* Scan the brigade looking for heap-buckets */
++    
+     _DBG("Scanning the brigade",0);
+     bucket = APR_BRIGADE_FIRST(bb);
+     while (bucket != APR_BRIGADE_SENTINEL(bb) &&
+@@ -1294,12 +1386,22 @@
+     /* -- receive data from socket -- */
+     apr_os_sock_get(&ctrl_sock_fd, lr->sd);
+     _DBG("receiving from sock_fd=%d", ctrl_sock_fd);
+-    ret = recvmsg(ctrl_sock_fd, &msg, 0);
+ 
+-    if(ret == -1)
+-      _DBG("recvmsg failed with error \"%s\"", strerror(errno));
+-    else
+-      _DBG("recvmsg returned %d", ret);
++    // Don't block
++    ret = recvmsg(ctrl_sock_fd, &msg, MSG_DONTWAIT);
++
++    if (ret == -1 && errno == EAGAIN) {
++        _DBG("receive_from_multiplexer recvmsg() EAGAIN, someone was faster");
++        
++        return APR_EAGAIN;
++    }
++    else if (ret == -1) {
++        _DBG("recvmsg failed with error \"%s\"", strerror(errno));
++        
++        // Error, better kill this child to be on the safe side
++        return APR_EGENERAL;
++    }
++    else _DBG("recvmsg returned %d", ret);
+ 
+     /* -- extract socket from the cmsg -- */
+     memcpy(&trans_sock_fd, CMSG_DATA(cmsg), sizeof(trans_sock_fd));
+@@ -1399,10 +1501,58 @@
+     return 0;
+ }
+ 
+-static int peruser_setup_child(int childnum)
++static int peruser_setup_cgroup(int childnum, server_env_t *senv, apr_pool_t *pool)
++{
++    apr_file_t *file;
++    int length;
++    apr_size_t content_len;
++    char *tasks_file, *content, *pos;
++
++    _DBG("starting to add pid to cgroup %s", senv->cgroup);
++
++    length = strlen(senv->cgroup) + CGROUP_TASKS_FILE_LEN;
++    tasks_file = malloc(length);
++
++    if (!tasks_file) return -1;
++
++    pos = apr_cpystrn(tasks_file, senv->cgroup, length);
++    apr_cpystrn(pos, CGROUP_TASKS_FILE, CGROUP_TASKS_FILE_LEN);
++
++    /* Prepare the data to be written to tasks file */
++    content = apr_itoa(pool, ap_my_pid);
++    content_len  = strlen(content);
++
++    _DBG("writing pid %s to tasks file %s", content, tasks_file);
++
++    if (apr_file_open(&file, tasks_file, APR_WRITE, APR_OS_DEFAULT, pool)) {
++        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
++                     "cgroup: unable to open file %s",
++                     tasks_file);
++        free(tasks_file);
++        return OK; /* don't fail if cgroup not available */
++    }
++
++    if (apr_file_write(file, content, &content_len)) {
++   	ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
++                     "cgroup: unable to write pid to file %s",
++                     tasks_file);
++    }
++
++    apr_file_close(file);
++
++    free(tasks_file);
++
++    return OK;
++}
++
++static int peruser_setup_child(int childnum, apr_pool_t *pool)
+ {
+     server_env_t *senv = CHILD_INFO_TABLE[childnum].senv;
+ 
++    if (senv->nice_lvl != 0) {
++        nice(senv->nice_lvl);
++    }
++
+     if(senv->chroot) {
+       _DBG("chdir to %s", senv->chroot);
+       if(chdir(senv->chroot)) {
+@@ -1421,6 +1571,10 @@
+       }
+     }
+ 
++    if(senv->cgroup) {
++   	peruser_setup_cgroup(childnum, senv, pool);
++    }
++
+     if (senv->uid == -1 && senv->gid == -1) {
+         return unixd_setup_child();
+     }
+@@ -1594,15 +1748,6 @@
+     {
+         case CHILD_TYPE_MULTIPLEXER:
+             _DBG("MULTIPLEXER %d", my_child_num);
+-
+-            /* update status on processors that are ready to accept requests */
+-            _DBG("updating processor stati", 0);
+-            for(i = 0; i < NUM_CHILDS; ++i)
+-            {
+-                if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY)
+-                    CHILD_INFO_TABLE[i].status = CHILD_STATUS_ACTIVE;
+-            }
+-
+             break;
+ 
+         case CHILD_TYPE_PROCESSOR:
+@@ -1626,7 +1771,7 @@
+     apr_os_sock_put(&pod_sock, &fd, pconf);
+     listen_add(pconf, pod_sock, check_pipe_of_death);
+ 
+-    if(peruser_setup_child(my_child_num) != 0)
++    if(peruser_setup_child(my_child_num, pchild) != 0)
+         clean_child_exit(APEXIT_CHILDFATAL);
+ 
+     ap_run_child_init(pchild, ap_server_conf);
+@@ -1670,14 +1815,19 @@
+ 	    clean_child_exit(0);
+ 	}
+ 
+-	(void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
++        (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
++
++        CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_READY;
++        _DBG("Child %d (%s) is now ready", my_child_num, child_type_string(CHILD_INFO_TABLE[my_child_num].type));
+ 
+ 	/*
+ 	 * Wait for an acceptable connection to arrive.
+ 	 */
+ 
+-	/* Lock around "accept", if necessary */
+-	SAFE_ACCEPT(accept_mutex_on());
++        /* Lock around "accept", if necessary */
++        if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
++            SAFE_ACCEPT(accept_mutex_on());
++        }
+ 
+         if (num_listensocks == 1) {
+             offset = 0;
+@@ -1729,18 +1879,27 @@
+          * defer the exit
+          */
+         status = listensocks[offset].accept_func((void *)&sock, &listensocks[offset], ptrans);
+-        SAFE_ACCEPT(accept_mutex_off()); 	/* unlock after "accept" */
++
++        if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
++            SAFE_ACCEPT(accept_mutex_off()); 	/* unlock after "accept" */
++        }
+ 
+         if (status == APR_EGENERAL) {
+             /* resource shortage or should-not-occur occured */
+             clean_child_exit(1);
+         }
+-        else if (status != APR_SUCCESS || die_now) {
++        else if (status != APR_SUCCESS || die_now || sock == NULL) {
+             continue;
+         }
+ 
++        if (CHILD_INFO_TABLE[my_child_num].status == CHILD_STATUS_READY) {
++            CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_ACTIVE;
++            _DBG("Child %d (%s) is now active", my_child_num, child_type_string(CHILD_INFO_TABLE[my_child_num].type));
++        }
++
+         if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_PROCESSOR ||
+-            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER)
++            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER ||
++            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER)
+         {
+           _DBG("CHECKING IF WE SHOULD CLONE A CHILD...");
+ 
+@@ -1754,8 +1913,11 @@
+ 
+           if(total_processors(my_child_num) <
+               CHILD_INFO_TABLE[my_child_num].senv->max_processors &&
+-            idle_processors(my_child_num) <=
+-              CHILD_INFO_TABLE[my_child_num].senv->min_free_processors)
++            (idle_processors(my_child_num) <=
++              CHILD_INFO_TABLE[my_child_num].senv->min_free_processors ||
++             total_processors(my_child_num) <
++              CHILD_INFO_TABLE[my_child_num].senv->min_processors
++            ))
+           {
+               _DBG("CLONING CHILD");
+               child_clone();
+@@ -1804,46 +1966,80 @@
+     clean_child_exit(0);
+ }
+ 
+-static server_env_t* senv_add(int uid, int gid, const char* chroot)
+-{
++static server_env_t* find_senv_by_name(const char *name) {
+     int i;
+-    int socks[2];
+ 
+-    _DBG("Searching for matching senv...");
++    if (name == NULL) return NULL;
++
++    _DBG("name=%s", name);
++
++    for(i = 0; i < NUM_SENV; i++)
++      {
++          if(SENV[i].name != NULL && !strcmp(SENV[i].name, name)) {
++              return &SENV[i];
++          }
++      }
++
++    return NULL;
++}
++
++static server_env_t* find_matching_senv(server_env_t* senv) {
++    int i;
++
++    _DBG("name=%s uid=%d gid=%d chroot=%s", senv->name, senv->uid, senv->gid, senv->chroot);
+ 
+     for(i = 0; i < NUM_SENV; i++)
+-    {
+-      if(SENV[i].uid == uid && SENV[i].gid == gid &&
+-         (SENV[i].chroot == NULL || !strcmp(SENV[i].chroot, chroot)))
+       {
+-          _DBG("Found existing senv: %i", i);
+-          return &SENV[i];
++          if((senv->name != NULL && SENV[i].name != NULL && !strcmp(SENV[i].name, senv->name)) ||
++             (senv->name == NULL && SENV[i].uid == senv->uid && SENV[i].gid == senv->gid &&
++              (
++               (SENV[i].chroot == NULL && senv->chroot == NULL) ||
++               ((SENV[i].chroot != NULL || senv->chroot != NULL) && !strcmp(SENV[i].chroot, senv->chroot)))
++              )
++             ) {
++              return &SENV[i];
++          }
+       }
++
++    return NULL;
++}
++
++static server_env_t* senv_add(server_env_t *senv)
++{
++    int socks[2];
++    server_env_t *old_senv;
++
++    _DBG("Searching for matching senv...");
++
++    old_senv = find_matching_senv(senv);
++
++    if (old_senv) {
++        _DBG("Found existing senv");
++        senv = old_senv;
++        return old_senv;
+     }
+ 
+     if(NUM_SENV >= server_limit)
+-    {
+-      _DBG("server_limit reached!");
+-      return NULL;
+-    }
++      {
++          _DBG("server_limit reached!");
++          return NULL;
++      }
+ 
+     _DBG("Creating new senv");
+ 
+-    SENV[NUM_SENV].uid = uid;
+-    SENV[NUM_SENV].gid = gid;
+-    SENV[NUM_SENV].chroot = chroot;
+-
+-    SENV[NUM_SENV].min_processors = ap_min_processors;
+-    SENV[NUM_SENV].min_free_processors = ap_min_free_processors;
+-    SENV[NUM_SENV].max_processors = ap_max_processors;
++    memcpy(&SENV[NUM_SENV], senv, sizeof(server_env_t));
++
++    SENV[NUM_SENV].availability = 100;
+ 
+     socketpair(PF_UNIX, SOCK_STREAM, 0, socks);
+     SENV[NUM_SENV].input  = socks[0];
+     SENV[NUM_SENV].output = socks[1];
+ 
++    senv = &SENV[NUM_SENV];
+     return &SENV[server_env_image->control->num++];
+ }
+ 
++
+ static const char* child_clone()
+ {
+     int i;
+@@ -1869,7 +2065,14 @@
+     new = &CHILD_INFO_TABLE[i];
+ 
+     new->senv = this->senv;
+-    new->type = CHILD_TYPE_WORKER;
++
++    if (this->type == CHILD_TYPE_MULTIPLEXER) {
++        new->type = CHILD_TYPE_MULTIPLEXER;
++    }
++    else {
++        new->type = CHILD_TYPE_WORKER;
++    }
++
+     new->sock_fd = this->sock_fd;
+     new->status = CHILD_STATUS_STARTING;
+ 
+@@ -1878,7 +2081,7 @@
+ }
+ 
+ static const char* child_add(int type, int status,
+-                             apr_pool_t *pool, uid_t uid, gid_t gid, const char* chroot)
++                             apr_pool_t *pool, server_env_t *senv)
+ {
+     _DBG("adding child #%d", NUM_CHILDS);
+ 
+@@ -1888,10 +2091,10 @@
+                "Increase NumServers in your config file.";
+     }
+ 
+-       if (chroot && !ap_is_directory(pool, chroot))
+-               return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", chroot);
++       if (senv->chroot && !ap_is_directory(pool, senv->chroot))
++               return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", senv->chroot);
+ 
+-    CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(uid, gid, chroot);
++    CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(senv);
+ 
+     if(CHILD_INFO_TABLE[NUM_CHILDS].senv == NULL)
+     {
+@@ -1907,10 +2110,10 @@
+     CHILD_INFO_TABLE[NUM_CHILDS].status = status;
+ 
+     _DBG("[%d] uid=%d gid=%d type=%d chroot=%s",
+-         NUM_CHILDS, uid, gid, type,
+-         chroot);
++         NUM_CHILDS, senv->uid, senv->gid, type,
++         senv->chroot);
+ 
+-    if (uid == 0 || gid == 0)
++    if (senv->uid == 0 || senv->gid == 0)
+     {
+         _DBG("Assigning root user/group to a child.", 0);
+     }
+@@ -1957,7 +2160,7 @@
+     (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING,
+                                                (request_rec *) NULL);
+ 
+-    CHILD_INFO_TABLE[slot].status = CHILD_STATUS_ACTIVE;
++    CHILD_INFO_TABLE[slot].status = CHILD_STATUS_READY;
+ 
+ 
+ #ifdef _OSD_POSIX
+@@ -2062,19 +2265,31 @@
+         if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING)
+           make_child(ap_server_conf, i);
+       }
+-      else if(((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR || 
+-               CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)  &&
+-               ap_scoreboard_image->parent[i].pid > 1) &&
+-               (idle_processors (i) > 1 || total_processes (i) == 1) && (
+-                   (expire_timeout > 0 &&  ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && 
+-                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) ||
+-                   (idle_timeout >   0 &&  ap_scoreboard_image->servers[i][0].status == SERVER_READY &&  
+-                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout)))
++      else if(
++    	      (((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR ||
++                 CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)  &&
++                ap_scoreboard_image->parent[i].pid > 1) &&
++               (idle_processors (i) > CHILD_INFO_TABLE[i].senv->min_free_processors || CHILD_INFO_TABLE[i].senv->min_free_processors == 0) &&
++               total_processes (i) > CHILD_INFO_TABLE[i].senv->min_processors && 
++               (
++                (expire_timeout > 0 &&  ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && 
++                 apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) ||
++                (idle_timeout >   0 &&  ap_scoreboard_image->servers[i][0].status == SERVER_READY &&  
++                 apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout) ||
++                (CHILD_INFO_TABLE[i].senv->max_free_processors > 0 && CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY &&
++                 idle_processors(i) > CHILD_INFO_TABLE[i].senv->max_free_processors))
++               )
++              || (CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER &&
++                  (multiplexer_idle_timeout > 0 && ap_scoreboard_image->servers[i][0].status == SERVER_READY &&
++                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > multiplexer_idle_timeout) &&
++                  total_processors(i) > CHILD_INFO_TABLE[i].senv->min_processors
++                  )
++            )
+       {
+         CHILD_INFO_TABLE[i].pid = 0;
+         CHILD_INFO_TABLE[i].status = CHILD_STATUS_STANDBY;
+ 
+-        if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)
++        if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER || CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER)
+         {
+           /* completely free up this slot */
+ 
+@@ -2173,7 +2388,6 @@
+         return 1;
+     }
+ 
+-#if 0
+ #if APR_USE_SYSVSEM_SERIALIZE
+     if (ap_accept_lock_mech == APR_LOCK_DEFAULT || 
+         ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
+@@ -2189,7 +2403,6 @@
+             return 1;
+         }
+     }
+-#endif
+ 
+     if (!is_graceful) {
+         if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
+@@ -2598,7 +2811,10 @@
+     ap_listen_pre_config();
+     ap_min_processors = DEFAULT_MIN_PROCESSORS;
+     ap_min_free_processors = DEFAULT_MIN_FREE_PROCESSORS;
++    ap_max_free_processors = DEFAULT_MAX_FREE_PROCESSORS;
+     ap_max_processors = DEFAULT_MAX_PROCESSORS;
++    ap_min_multiplexers = DEFAULT_MIN_MULTIPLEXERS;
++    ap_max_multiplexers = DEFAULT_MAX_MULTIPLEXERS;
+     ap_daemons_limit = server_limit;
+     ap_pid_fname = DEFAULT_PIDLOG;
+     ap_lock_fname = DEFAULT_LOCKFILE;
+@@ -2608,6 +2824,13 @@
+ 	ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
+ #endif
+ 
++    expire_timeout = DEFAULT_EXPIRE_TIMEOUT;
++    idle_timeout = DEFAULT_IDLE_TIMEOUT;
++    multiplexer_idle_timeout = DEFAULT_MULTIPLEXER_IDLE_TIMEOUT;
++    processor_wait_timeout = DEFAULT_PROCESSOR_WAIT_TIMEOUT;
++    processor_wait_steps = DEFAULT_PROCESSOR_WAIT_STEPS;
++
++
+     apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
+ 
+     /* we need to know ServerLimit and ThreadLimit before we start processing
+@@ -2709,11 +2932,13 @@
+         server_env_image->control = (server_env_control*)shmem;
+         shmem += sizeof(server_env_control*);
+         server_env_image->table = (server_env_t*)shmem;
++    }
+ 
++    if(restart_num <= 2) {
++        _DBG("Cleaning server environments table");
++    
+         server_env_image->control->num = 0;
+-
+-        for (i = 0; i < tmp_server_limit; i++)
+-        {
++        for (i = 0; i < tmp_server_limit; i++) {
+             SENV[i].processor_id = -1;
+             SENV[i].uid          = -1;
+             SENV[i].gid          = -1;
+@@ -2781,8 +3006,8 @@
+                 if (pass_request(r, processor) == -1)
+                 {
+                     ap_log_error(APLOG_MARK, APLOG_ERR, 0,
+-                             ap_server_conf, "Could not pass request to proper "                             "child, request will not be honoured.");
+-                    return DECLINED;
++                                 ap_server_conf, "Could not pass request to processor %s (virtualhost %s), request will not be honoured.",
++                                 processor->senv->name, r->hostname);
+                 }
+                 _DBG("doing longjmp",0);
+                 longjmp(CHILD_INFO_TABLE[my_child_num].jmpbuffer, 1);
+@@ -2859,32 +3084,37 @@
+     ap_rputs("<hr>\n", r);
+     ap_rputs("<h2>peruser status</h2>\n", r);
+     ap_rputs("<table border=\"0\">\n", r);
+-    ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>TYPE</td><td>UID</td>"
+-                   "<td>GID</td><td>CHROOT</td><td>INPUT</td>"
++    ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>SB STATUS</td><td>TYPE</td><td>UID</td>"
++                   "<td>GID</td><td>CHROOT</td><td>NICE</td><td>INPUT</td>"
+                    "<td>OUTPUT</td><td>SOCK_FD</td>"
+                    "<td>TOTAL PROCESSORS</td><td>MAX PROCESSORS</td>"
+-                   "<td>IDLE PROCESSORS</td><td>MIN FREE PROCESSORS</td></tr>\n", r);
++                   "<td>IDLE PROCESSORS</td><td>MIN FREE PROCESSORS</td>"
++                   "<td>AVAIL</td>"
++                   "</tr>\n", r);
+     for (x = 0; x < NUM_CHILDS; x++)
+         {
+         senv = CHILD_INFO_TABLE[x].senv;
+-        ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%12s</td>"
+-                       "<td>%4d</td><td>%4d</td><td>%25s</td><td>%5d</td>"
++        ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%8s</td><td>%12s</td>"
++                       "<td>%4d</td><td>%4d</td><td>%25s</td><td>%3d</td><td>%5d</td>"
+                        "<td>%6d</td><td>%7d</td><td>%d</td><td>%d</td>"
+-                       "<td>%d</td><td>%d</td></tr>\n", 
++                       "<td>%d</td><td>%d</td><td>%3d</td></tr>\n",
+                        CHILD_INFO_TABLE[x].id, 
+                        CHILD_INFO_TABLE[x].pid, 
+                        child_status_string(CHILD_INFO_TABLE[x].status), 
++                       scoreboard_status_string(SCOREBOARD_STATUS(x)),
+                        child_type_string(CHILD_INFO_TABLE[x].type), 
+                        senv == NULL ? -1 : senv->uid, 
+                        senv == NULL ? -1 : senv->gid, 
+                        senv == NULL ? NULL : senv->chroot, 
++                       senv == NULL ? 0 : senv->nice_lvl,
+                        senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->input, 
+                        senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->output, 
+                        CHILD_INFO_TABLE[x].sock_fd,
+                        total_processors(x), 
+                        senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->max_processors,
+                        idle_processors(x),
+-                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors
++                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors,
++                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->availability
+                        );
+        }
+     ap_rputs("</table>\n", r);
+@@ -2938,50 +3168,183 @@
+     APR_OPTIONAL_HOOK(ap, status_hook, peruser_status_hook, NULL, NULL, APR_HOOK_MIDDLE);
+ }
+ 
+-/* we define an Processor w/ specific uid/gid */
+-static const char *cf_Processor(cmd_parms *cmd, void *dummy,
+-    const char *user_name, const char *group_name, const char *chroot)
++static const char *cf_Processor(cmd_parms *cmd, void *dummy, const char *arg)
+ {
+-    uid_t uid = ap_uname2id(user_name);
+-    gid_t gid = ap_gname2id(group_name);
++    const char *user_name = NULL, *group_name = NULL, *directive;
++    server_env_t senv;
++    ap_directive_t *current;
++
++    const char *endp = ap_strrchr_c(arg, '>');
++
++    if (endp == NULL) {
++	return apr_psprintf(cmd->temp_pool,
++			    "Error: Directive %s> missing closing '>'", cmd->cmd->name);
++    }
++
++    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
++
++    if (!arg) {
++   	return apr_psprintf(cmd->temp_pool,
++                            "Error: %s> must specify a processor name", cmd->cmd->name);
++    }
++
++    senv.name = ap_getword_conf(cmd->pool, &arg);
++    _DBG("processor_name: %s", senv.name);
++
++    if (strlen(senv.name) == 0) {
++        return apr_psprintf(cmd->temp_pool,
++                            "Error: Directive %s> takes one argument", cmd->cmd->name);
++    }
++
++    /*	Check for existing processors on first launch and between gracefuls */
++    if (restart_num == 1 || is_graceful) {
++        server_env_t *old_senv = find_senv_by_name(senv.name);
++
++        if (old_senv) {
++            return apr_psprintf(cmd->temp_pool,
++                                "Error: Processor %s already defined", senv.name);
++        }
++    }
++
++    senv.nice_lvl 		= 0;
++    senv.chroot 		= NULL;
++    senv.cgroup			= NULL;
++    senv.min_processors 	= ap_min_processors;
++    senv.min_free_processors 	= ap_min_free_processors;
++    senv.max_free_processors    = ap_max_free_processors;
++    senv.max_processors 	= ap_max_processors;
++
++    current = cmd->directive->first_child;
++
++    int proc_temp = 0;
++    for(; current != NULL; current = current->next) {
++        directive = current->directive;
++        
++        if (!strcasecmp(directive, "user")) {
++            user_name = current->args;
++        }
++        else if (!strcasecmp(directive, "group")) {
++   	    group_name = current->args;
++        }
++        else if (!strcasecmp(directive, "chroot")) {
++            senv.chroot = ap_getword_conf(cmd->pool, &current->args);
++        }
++        else if (!strcasecmp(directive, "nicelevel")) {
++    	    senv.nice_lvl = atoi(current->args);
++        }
++        else if (!strcasecmp(directive, "maxprocessors")) {
++            proc_temp = atoi(current->args);
++
++            if (proc_temp < 1) {
++                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                             "WARNING: Require MaxProcessors > 0, setting to 1");
++                proc_temp = 1;
++            }
++
++            senv.max_processors = proc_temp;
++        }
++        else if (!strcasecmp(directive, "minprocessors")) {
++            proc_temp = atoi(current->args);
++
++            if (proc_temp < 0) {
++                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                             "WARNING: Require MinProcessors >= 0, setting to 0");
++                proc_temp = 0;
++            }
++
++            senv.min_processors = proc_temp;
++        }
++        else if (!strcasecmp(directive, "minspareprocessors")) {
++            proc_temp = atoi(current->args);
+ 
+-    _DBG("user=%s:%d group=%s:%d chroot=%s",
+-        user_name, uid, group_name, gid, chroot);
++            if (proc_temp < 0) {
++                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                             "WARNING: Require MinSpareProcessors >= 0, setting to 0");
++                proc_temp = 0;
++            }
++
++            senv.min_free_processors = proc_temp;
++        }
++        else if (!strcasecmp(directive, "maxspareprocessors")) {
++            proc_temp = atoi(current->args);
++            
++            if (proc_temp < 0) {
++                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                             "WARNING: Require MaxSpareProcessors >= 0, setting to 0");
++                proc_temp = 0;
++            }
++
++            senv.max_free_processors = proc_temp;
++        }
++        else if (!strcasecmp(directive, "cgroup")) {
++            senv.cgroup = ap_getword_conf(cmd->pool, &current->args);
++        }
++        else {
++            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                         "Unknown directive %s in %s>", directive, cmd->cmd->name);
++        }
++    }
++
++    if (user_name == NULL || group_name == NULL) {
++        return apr_psprintf(cmd->temp_pool,
++                            "Error: User or Group must be set in %s>", cmd->cmd->name);
++    }
++
++    senv.uid = ap_uname2id(user_name);
++    senv.gid = ap_gname2id(group_name);
++
++    _DBG("name=%s user=%s:%d group=%s:%d chroot=%s nice_lvl=%d",
++         senv.name, user_name, senv.uid, group_name, senv.gid, senv.chroot, senv.nice_lvl);
++
++    _DBG("min_processors=%d min_free_processors=%d max_spare_processors=%d max_processors=%d",
++         senv.min_processors, senv.min_free_processors, senv.max_free_processors, senv.max_processors);
+ 
+     return child_add(CHILD_TYPE_PROCESSOR, CHILD_STATUS_STANDBY,
+-                     cmd->pool, uid, gid, chroot);
++                     cmd->pool, &senv);
+ }
+ 
+ /* we define an Multiplexer child w/ specific uid/gid */
+ static const char *cf_Multiplexer(cmd_parms *cmd, void *dummy,
+     const char *user_name, const char *group_name, const char *chroot)
+ {
+-    uid_t uid = ap_uname2id(user_name);
+-    gid_t gid = ap_gname2id(group_name);
++    server_env_t senv;
++
++    senv.name 		= NULL;
++
++    senv.uid 		= ap_uname2id(user_name);
++    senv.gid 		= ap_gname2id(group_name);
++    senv.nice_lvl 	= 0;
++    senv.cgroup		= NULL;
++    senv.chroot         = chroot;
++
++    senv.min_processors 	= ap_min_multiplexers;
++    senv.min_free_processors 	= ap_min_free_processors;
++    senv.max_free_processors    = ap_max_free_processors;
++    senv.max_processors 	= ap_max_multiplexers;
+ 
+     _DBG("user=%s:%d group=%s:%d chroot=%s [multiplexer id %d]",
+-        user_name, uid, group_name, gid, chroot, NUM_CHILDS);
++        user_name, senv.uid, group_name, senv.gid, senv.chroot, NUM_CHILDS);
+ 
+     return child_add(CHILD_TYPE_MULTIPLEXER, CHILD_STATUS_STARTING,
+-                     cmd->pool, uid, gid, chroot);
++                     cmd->pool, &senv);
+ }
+ 
+ static const char* cf_ServerEnvironment(cmd_parms *cmd, void *dummy,
+-    const char *user_name, const char *group_name, const char *chroot)
++    const char *name)
+ {
+-    int uid = ap_uname2id(user_name);
+-    int gid = ap_gname2id(group_name);
+     peruser_server_conf *sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
+ 
+     _DBG("function entered", 0);
+ 
+-       if (chroot && !ap_is_directory(cmd->pool, chroot))
+-               return apr_psprintf(cmd->pool, "Error: chroot directory [%s] does not exist", chroot);
++    sconf->senv = find_senv_by_name(name);
+ 
+-    sconf->senv = senv_add(uid, gid, chroot);
++    if (sconf->senv == NULL) {
++        return apr_psprintf(cmd->pool,
++                            "Error: Processor %s not defined", name);
++    }
+ 
+-    _DBG("user=%s:%d group=%s:%d chroot=%s numchilds=%d",
+-        user_name, uid, group_name, gid, chroot, NUM_CHILDS);
++    _DBG("user=%d group=%d chroot=%s numchilds=%d",
++        sconf->senv->uid, sconf->senv->gid, sconf->senv->chroot, NUM_CHILDS);
+ 
+     return NULL;
+ }
+@@ -3046,10 +3409,10 @@
+ 
+     min_procs = atoi(arg);
+ 
+-    if (min_procs < 1) {
++    if (min_procs < 0) {
+         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+-                     "WARNING: Require MaxProcessors > 0, setting to 1");
+-        min_procs = 1;
++                     "WARNING: Require MinProcessors >= 0, setting to 0");
++        min_procs = 0;
+     }
+ 
+     if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
+@@ -3075,10 +3438,10 @@
+ 
+     min_free_procs = atoi(arg);
+ 
+-    if (min_free_procs < 1) {
++    if (min_free_procs < 0) {
+         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+-                     "WARNING: Require MinSpareProcessors > 0, setting to 1");
+-        min_free_procs = 1;
++                     "WARNING: Require MinSpareProcessors >= 0, setting to 0");
++        min_free_procs = 0;
+     }
+ 
+     if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
+@@ -3092,6 +3455,35 @@
+     return NULL;
+ }
+ 
++static const char *set_max_free_processors (cmd_parms *cmd, void *dummy, const char *arg)
++{
++     peruser_server_conf *sconf;
++     int max_free_procs;
++     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
++
++     if (err != NULL) {
++         return err;
++     }
++
++     max_free_procs = atoi(arg);
++
++     if (max_free_procs < 0) {
++         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                      "WARNING: Require MaxSpareProcessors >= 0, setting to 0");
++         max_free_procs = 0;
++     }
++
++     if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
++         sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
++         sconf->senv->max_free_processors = max_free_procs;
++     }
++     else {
++         ap_max_free_processors = max_free_procs;
++     }
++
++     return NULL;
++}
++
+ static const char *set_max_processors (cmd_parms *cmd, void *dummy, const char *arg)
+ {
+     peruser_server_conf *sconf;
+@@ -3121,6 +3513,50 @@
+     return NULL;
+ }
+ 
++static const char *set_min_multiplexers (cmd_parms *cmd, void *dummy, const char *arg)
++{
++    int min_multiplexers;
++    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
++
++    if (err != NULL) {
++        return err;
++    }
++
++    min_multiplexers = atoi(arg);
++
++    if (min_multiplexers < 1) {
++        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                     "WARNING: Require MinMultiplexers > 0, setting to 1");
++        min_multiplexers = 1;
++    }
++
++    ap_min_multiplexers = min_multiplexers;
++
++    return NULL;
++}
++
++static const char *set_max_multiplexers (cmd_parms *cmd, void *dummy, const char *arg)
++{
++    int max_multiplexers;
++    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
++
++    if (err != NULL) {
++        return err;
++    }
++
++    max_multiplexers = atoi(arg);
++
++    if (max_multiplexers < 1) {
++        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                     "WARNING: Require MaxMultiplexers > 0, setting to 1");
++        max_multiplexers = 1;
++    }
++
++    ap_max_multiplexers = max_multiplexers;
++
++    return NULL;
++}
++
+ static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) 
+ {
+     int tmp_server_limit;
+@@ -3183,6 +3619,42 @@
+     return NULL;
+ }
+ 
++static const char *set_multiplexer_idle_timeout (cmd_parms *cmd, void *dummy, const char *arg) {
++    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
++
++    if (err != NULL) {
++        return err;
++    }
++
++    multiplexer_idle_timeout = atoi(arg);
++
++    return NULL;
++}
++
++static const char *set_processor_wait_timeout (cmd_parms *cmd, void *dummy, const char *timeout, const char *steps) {
++    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
++    
++    if (err != NULL) {
++        return err;
++    }
++
++    processor_wait_timeout = atoi(timeout);
++
++    if (steps != NULL) {
++        int steps_tmp = atoi(steps);
++
++        if (steps_tmp < 1) {
++            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                         "WARNING: Require ProcessorWaitTimeout steps > 0, setting to 1");
++            steps_tmp = 1;
++        }
++
++        processor_wait_steps = steps_tmp;
++    }
++
++    return NULL;
++}
++
+ static const command_rec peruser_cmds[] = {
+ UNIX_DAEMON_COMMANDS,
+ LISTEN_COMMANDS,
+@@ -3190,23 +3662,33 @@
+               "Minimum number of idle children, to handle request spikes"),
+ AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
+               "Minimum number of idle children, to handle request spikes"),
++AP_INIT_TAKE1("MaxSpareProcessors", set_max_free_processors, NULL, RSRC_CONF,
++              "Maximum number of idle children, 0 to disable"),
+ AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
+               "Maximum number of children alive at the same time"),
+ AP_INIT_TAKE1("MinProcessors", set_min_processors, NULL, RSRC_CONF,
+               "Minimum number of processors per vhost"),
+ AP_INIT_TAKE1("MaxProcessors", set_max_processors, NULL, RSRC_CONF,
+               "Maximum number of processors per vhost"),
++AP_INIT_TAKE1("MinMultiplexers", set_min_multiplexers, NULL, RSRC_CONF,
++              "Minimum number of multiplexers the server can have"),
++AP_INIT_TAKE1("MaxMultiplexers", set_max_multiplexers, NULL, RSRC_CONF,
++              "Maximum number of multiplexers the server can have"),
+ AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
+               "Maximum value of MaxClients for this run of Apache"),
+ AP_INIT_TAKE1("ExpireTimeout", set_expire_timeout, NULL, RSRC_CONF,
+-              "Maximum idle time before a child is killed, 0 to disable"),
++              "Maximum time a child can live, 0 to disable"),
+ AP_INIT_TAKE1("IdleTimeout", set_idle_timeout, NULL, RSRC_CONF,
+               "Maximum time before a child is killed after being idle, 0 to disable"),
++AP_INIT_TAKE1("MultiplexerIdleTimeout", set_multiplexer_idle_timeout, NULL, RSRC_CONF,
++              "Maximum time before a multiplexer is killed after being idle, 0 to disable"),
++AP_INIT_TAKE12("ProcessorWaitTimeout", set_processor_wait_timeout, NULL, RSRC_CONF,
++              "Maximum time a multiplexer waits for the processor if it is busy"),
+ AP_INIT_TAKE23("Multiplexer", cf_Multiplexer, NULL, RSRC_CONF,
+               "Specify an Multiplexer Child configuration."),
+-AP_INIT_TAKE23("Processor", cf_Processor, NULL, RSRC_CONF,
+-              "Specify a User and Group for a specific child process."),
+-AP_INIT_TAKE23("ServerEnvironment", cf_ServerEnvironment, NULL, RSRC_CONF,
++AP_INIT_RAW_ARGS("<Processor", cf_Processor, NULL, RSRC_CONF,
++              "Specify settings for processor."),
++AP_INIT_TAKE1("ServerEnvironment", cf_ServerEnvironment, NULL, RSRC_CONF,
+               "Specify the server environment for this virtual host."),
+ { NULL }
+ };


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:33 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:33 UTC (permalink / raw
  To: gentoo-commits

commit:     43035b7c2be4ecabdaf5f2f51d51e006a067acd9
Author:     Benedikt Boehm <hollow <AT> gentoo <DOT> org>
AuthorDate: Thu Oct  8 17:52:08 2009 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Thu Oct  8 17:52:08 2009 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=43035b7c

update to peruser 0.4.0 beta1

---
 ...er_0.3.0.patch => 20_all_peruser_0.4.0b1.patch} | 1531 +++++++++++++++-----
 2.2/patches/22_all_peruser_0.3.0-dc3.patch         | 1211 ----------------
 2 files changed, 1139 insertions(+), 1603 deletions(-)

diff --git a/2.2/patches/20_all_peruser_0.3.0.patch b/2.2/patches/20_all_peruser_0.4.0b1.patch
similarity index 72%
rename from 2.2/patches/20_all_peruser_0.3.0.patch
rename to 2.2/patches/20_all_peruser_0.4.0b1.patch
index c5cdc58..8e30e64 100644
--- a/2.2/patches/20_all_peruser_0.3.0.patch
+++ b/2.2/patches/20_all_peruser_0.4.0b1.patch
@@ -1,7 +1,44 @@
-Index: httpd-2.2.6/server/mpm/config.m4
-===================================================================
---- httpd-2.2.6.orig/server/mpm/config.m4
-+++ httpd-2.2.6/server/mpm/config.m4
+diff -Nur httpd-2.2.13/modules/ssl/mod_ssl.h httpd-2.2.13-peruser/modules/ssl/mod_ssl.h
+--- httpd-2.2.13/modules/ssl/mod_ssl.h	2006-07-12 06:38:44.000000000 +0300
++++ httpd-2.2.13-peruser/modules/ssl/mod_ssl.h	2009-09-01 16:19:22.000000000 +0300
+@@ -50,6 +50,10 @@
+  * is using SSL/TLS. */
+ APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
+ 
++/** An optional function which returns non-zero if the given server
++ * is using SSL/TLS. */
++APR_DECLARE_OPTIONAL_FN(int, ssl_server_is_https, (server_rec *));
++
+ /** The ssl_proxy_enable() and ssl_engine_disable() optional functions
+  * are used by mod_proxy to enable use of SSL for outgoing
+  * connections. */
+diff -Nur httpd-2.2.13/modules/ssl/ssl_engine_vars.c httpd-2.2.13-peruser/modules/ssl/ssl_engine_vars.c
+--- httpd-2.2.13/modules/ssl/ssl_engine_vars.c	2009-08-06 10:28:47.000000000 +0300
++++ httpd-2.2.13-peruser/modules/ssl/ssl_engine_vars.c	2009-09-01 16:19:22.000000000 +0300
+@@ -58,6 +58,12 @@
+     return sslconn && sslconn->ssl;
+ }
+ 
++static int ssl_server_is_https(server_rec *s)
++{
++    SSLSrvConfigRec *sslsrv = mySrvConfig(s);
++    return sslsrv && sslsrv->enabled;
++}
++
+ static const char var_interface[] = "mod_ssl/" MOD_SSL_VERSION;
+ static char var_library_interface[] = SSL_LIBRARY_TEXT;
+ static char *var_library = NULL;
+@@ -67,6 +73,7 @@
+     char *cp, *cp2;
+ 
+     APR_REGISTER_OPTIONAL_FN(ssl_is_https);
++    APR_REGISTER_OPTIONAL_FN(ssl_server_is_https);
+     APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
+     APR_REGISTER_OPTIONAL_FN(ssl_ext_lookup);
+ 
+diff -Nur httpd-2.2.13/server/mpm/config.m4 httpd-2.2.13-peruser/server/mpm/config.m4
+--- httpd-2.2.13/server/mpm/config.m4	2005-10-30 19:05:26.000000000 +0200
++++ httpd-2.2.13-peruser/server/mpm/config.m4	2009-09-01 16:19:22.000000000 +0300
 @@ -1,7 +1,7 @@
  AC_MSG_CHECKING(which MPM to use)
  AC_ARG_WITH(mpm,
@@ -11,7 +48,7 @@ Index: httpd-2.2.6/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,11 +57,10 @@ Index: httpd-2.2.6/server/mpm/config.m4
          return 0
      else
          return 1
-Index: httpd-2.2.6/server/mpm/experimental/peruser/AUTHORS
-===================================================================
---- /dev/null
-+++ httpd-2.2.6/server/mpm/experimental/peruser/AUTHORS
-@@ -0,0 +1,9 @@
+diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/AUTHORS httpd-2.2.13-peruser/server/mpm/experimental/peruser/AUTHORS
+--- httpd-2.2.13/server/mpm/experimental/peruser/AUTHORS	1970-01-01 03:00:00.000000000 +0300
++++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/AUTHORS	2009-09-01 16:19:22.000000000 +0300
+@@ -0,0 +1,11 @@
 +Enrico Weigelt <weigelt [at] metux.de> (MetuxMPM maintainer)
 +Sean Gabriel Heacock <gabriel [at] telana.com> (Peruser maintainer)
 +Stefan Seufert <stefan [at] seuf.de>
@@ -34,29 +70,28 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/AUTHORS
 +Bert <bert [at] ev6.net>
 +Leen Besselink <leen [at] consolejunkie.net>
 +Steve Amerige <mpm [at] fatbear.com>
-Index: httpd-2.2.6/server/mpm/experimental/peruser/Makefile.in
-===================================================================
---- /dev/null
-+++ httpd-2.2.6/server/mpm/experimental/peruser/Makefile.in
++Stefan Klingner <stefan.klingner [at] mephisto23.com> (Peruser maintainer)
++Michal Grzedzicki <lazy404 [at] gmail.com>
+diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/config.m4 httpd-2.2.13-peruser/server/mpm/experimental/peruser/config.m4
+--- httpd-2.2.13/server/mpm/experimental/peruser/config.m4	1970-01-01 03:00:00.000000000 +0300
++++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/config.m4	2009-09-01 16:19:22.000000000 +0300
+@@ -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.13/server/mpm/experimental/peruser/Makefile.in httpd-2.2.13-peruser/server/mpm/experimental/peruser/Makefile.in
+--- httpd-2.2.13/server/mpm/experimental/peruser/Makefile.in	1970-01-01 03:00:00.000000000 +0300
++++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/Makefile.in	2009-09-01 16:19:22.000000000 +0300
 @@ -0,0 +1,5 @@
 +
 +LTLIBRARY_NAME    = libperuser.la
 +LTLIBRARY_SOURCES = peruser.c
 +
 +include $(top_srcdir)/build/ltlib.mk
-Index: httpd-2.2.6/server/mpm/experimental/peruser/config.m4
-===================================================================
---- /dev/null
-+++ httpd-2.2.6/server/mpm/experimental/peruser/config.m4
-@@ -0,0 +1,3 @@
-+if test "$MPM_NAME" = "peruser" ; then
-+    APACHE_FAST_OUTPUT(server/mpm/experimental/$MPM_NAME/Makefile)
-+fi
-Index: httpd-2.2.6/server/mpm/experimental/peruser/mpm.h
-===================================================================
---- /dev/null
-+++ httpd-2.2.6/server/mpm/experimental/peruser/mpm.h
-@@ -0,0 +1,103 @@
+diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/mpm_default.h httpd-2.2.13-peruser/server/mpm/experimental/peruser/mpm_default.h
+--- httpd-2.2.13/server/mpm/experimental/peruser/mpm_default.h	1970-01-01 03:00:00.000000000 +0300
++++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/mpm_default.h	2009-09-01 16:19:22.000000000 +0300
+@@ -0,0 +1,162 @@
 +/* ====================================================================
 + * The Apache Software License, Version 1.1
 + *
@@ -115,56 +150,114 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/mpm.h
 + * University of Illinois, Urbana-Champaign.
 + */
 +
-+#include "httpd.h"
-+#include "mpm_default.h"
-+#include "scoreboard.h"
-+#include "unixd.h"
++#ifndef APACHE_MPM_DEFAULT_H
++#define APACHE_MPM_DEFAULT_H
 +
-+#ifndef APACHE_MPM_PERUSER_H
-+#define APACHE_MPM_PERUSER_H
++/* Number of processors to spawn off for each ServerEnvironment by default */
 +
-+#define PERUSER_MPM
++#ifndef DEFAULT_START_PROCESSORS
++#define DEFAULT_START_PROCESSORS 0
++#endif
 +
-+#define MPM_NAME "Peruser"
++/* Minimum number of running processors per ServerEnvironment */
 +
-+#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
-+#define AP_MPM_WANT_WAIT_OR_TIMEOUT
-+#define AP_MPM_WANT_PROCESS_CHILD_STATUS
-+#define AP_MPM_WANT_SET_PIDFILE
-+#define AP_MPM_WANT_SET_SCOREBOARD
-+#define AP_MPM_WANT_SET_LOCKFILE
-+#define AP_MPM_WANT_SET_MAX_REQUESTS
-+#define AP_MPM_WANT_SET_COREDUMPDIR
-+#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
-+#define AP_MPM_WANT_SIGNAL_SERVER
-+#define AP_MPM_WANT_SET_MAX_MEM_FREE
-+#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
++#ifndef DEFAULT_MIN_PROCESSORS
++#define DEFAULT_MIN_PROCESSORS 0
++#endif
 +
-+#define AP_MPM_USES_POD 1
-+#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-+#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-+#define MPM_ACCEPT_FUNC unixd_accept
++/* Minimum --- fewer than this, and more will be created */
 +
-+extern int ap_threads_per_child;
-+extern int ap_max_daemons_limit;
-+extern server_rec *ap_server_conf;
++#ifndef DEFAULT_MIN_FREE_PROCESSORS
++#define DEFAULT_MIN_FREE_PROCESSORS 2
++#endif
 +
-+/* Table of child status */
-+#define SERVER_DEAD 0
-+#define SERVER_DYING 1
-+#define SERVER_ALIVE 2
++/* Maximum --- more than this, and idle processors will be killed (0 = disable) */
 +
-+typedef struct ap_ctable {
-+    pid_t pid;
-+    unsigned char status;
-+} ap_ctable;
++#ifndef DEFAULT_MAX_FREE_PROCESSORS
++#define DEFAULT_MAX_FREE_PROCESSORS 0
++#endif
 +
-+#endif /* APACHE_MPM_PERUSER_H */
-Index: httpd-2.2.6/server/mpm/experimental/peruser/mpm_default.h
-===================================================================
---- /dev/null
-+++ httpd-2.2.6/server/mpm/experimental/peruser/mpm_default.h
-@@ -0,0 +1,110 @@
++/* Maximum processors per ServerEnvironment */
++
++#ifndef DEFAULT_MAX_PROCESSORS
++#define DEFAULT_MAX_PROCESSORS 10
++#endif
++
++/* File used for accept locking, when we use a file */
++#ifndef DEFAULT_LOCKFILE
++#define DEFAULT_LOCKFILE DEFAULT_REL_RUNTIMEDIR "/accept.lock"
++#endif
++
++/* Where the main/parent process's pid is logged */
++#ifndef DEFAULT_PIDLOG
++#define DEFAULT_PIDLOG DEFAULT_REL_RUNTIMEDIR "/httpd.pid"
++#endif
++
++/*
++ * Interval, in microseconds, between scoreboard maintenance.
++ */
++#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
++#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
++#endif
++
++/* Number of requests to try to handle in a single process.  If <= 0,
++ * the children don't die off.
++ */
++#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
++#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
++#endif
++
++/* Maximum multiplexers */
++
++#ifndef DEFAULT_MAX_MULTIPLEXERS
++#define DEFAULT_MAX_MULTIPLEXERS 20
++#endif
++
++/* Minimum multiplexers */
++
++#ifndef DEFAULT_MIN_MULTIPLEXERS
++#define DEFAULT_MIN_MULTIPLEXERS 3
++#endif
++
++/* Amount of time a child can run before it expires (0 = turn off) */
++
++#ifndef DEFAULT_EXPIRE_TIMEOUT
++#define DEFAULT_EXPIRE_TIMEOUT 1800
++#endif
++
++/* Amount of time a child can stay idle (0 = turn off) */
++
++#ifndef DEFAULT_IDLE_TIMEOUT
++#define DEFAULT_IDLE_TIMEOUT 900
++#endif
++
++/* Amount of time a multiplexer can stay idle (0 = turn off) */
++
++#ifndef DEFAULT_MULTIPLEXER_IDLE_TIMEOUT
++#define DEFAULT_MULTIPLEXER_IDLE_TIMEOUT 0
++#endif
++
++/* Amount of maximum time a multiplexer can wait for processor if it is busy (0 = never wait)
++ * This is decreased with every busy request
++ */
++
++#ifndef DEFAULT_PROCESSOR_WAIT_TIMEOUT
++#define DEFAULT_PROCESSOR_WAIT_TIMEOUT 5
++#endif
++
++/* The number of different levels there are when a multiplexer is waiting for processor
++ * (between maximum waiting time and no waiting)
++ */
++
++#ifndef DEFAULT_PROCESSOR_WAIT_STEPS
++#define DEFAULT_PROCESSOR_WAIT_STEPS 10
++#endif
++
++#endif /* AP_MPM_DEFAULT_H */
+diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/mpm.h httpd-2.2.13-peruser/server/mpm/experimental/peruser/mpm.h
+--- httpd-2.2.13/server/mpm/experimental/peruser/mpm.h	1970-01-01 03:00:00.000000000 +0300
++++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/mpm.h	2009-09-01 16:19:22.000000000 +0300
+@@ -0,0 +1,104 @@
 +/* ====================================================================
 + * The Apache Software License, Version 1.1
 + *
@@ -223,63 +316,57 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/mpm_default.h
 + * University of Illinois, Urbana-Champaign.
 + */
 +
-+#ifndef APACHE_MPM_DEFAULT_H
-+#define APACHE_MPM_DEFAULT_H
-+
-+/* Number of processors to spawn off for each ServerEnvironment by default */
-+
-+#ifndef DEFAULT_START_PROCESSORS
-+#define DEFAULT_START_PROCESSORS 0
-+#endif
-+
-+/* Minimum number of running processors per ServerEnvironment */
++#include "httpd.h"
++#include "mpm_default.h"
++#include "scoreboard.h"
++#include "unixd.h"
 +
-+#ifndef DEFAULT_MIN_PROCESSORS
-+#define DEFAULT_MIN_PROCESSORS 0
-+#endif
++#ifndef APACHE_MPM_PERUSER_H
++#define APACHE_MPM_PERUSER_H
 +
-+/* Minimum --- fewer than this, and more will be created */
++#define PERUSER_MPM
 +
-+#ifndef DEFAULT_MIN_FREE_PROCESSORS
-+#define DEFAULT_MIN_FREE_PROCESSORS 2
-+#endif
++#define MPM_NAME "Peruser"
 +
-+/* Maximum processors per ServerEnvironment */
++#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
++#define AP_MPM_WANT_WAIT_OR_TIMEOUT
++#define AP_MPM_WANT_PROCESS_CHILD_STATUS
++#define AP_MPM_WANT_SET_PIDFILE
++#define AP_MPM_WANT_SET_SCOREBOARD
++#define AP_MPM_WANT_SET_LOCKFILE
++#define AP_MPM_WANT_SET_MAX_REQUESTS
++#define AP_MPM_WANT_SET_COREDUMPDIR
++#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
++#define AP_MPM_WANT_SIGNAL_SERVER
++#define AP_MPM_WANT_SET_MAX_MEM_FREE
++#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
 +
-+#ifndef DEFAULT_MAX_PROCESSORS
-+#define DEFAULT_MAX_PROCESSORS 10
-+#endif
++#define AP_MPM_USES_POD 1
++#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
++#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
++#define MPM_VALID_PID(p) (getpgid(p) == getpgrp())
++#define MPM_ACCEPT_FUNC unixd_accept
 +
-+/* File used for accept locking, when we use a file */
-+#ifndef DEFAULT_LOCKFILE
-+#define DEFAULT_LOCKFILE DEFAULT_REL_RUNTIMEDIR "/accept.lock"
-+#endif
++extern int ap_threads_per_child;
++extern int ap_max_daemons_limit;
++extern server_rec *ap_server_conf;
 +
-+/* Where the main/parent process's pid is logged */
-+#ifndef DEFAULT_PIDLOG
-+#define DEFAULT_PIDLOG DEFAULT_REL_RUNTIMEDIR "/httpd.pid"
-+#endif
++/* Table of child status */
++#define SERVER_DEAD 0
++#define SERVER_DYING 1
++#define SERVER_ALIVE 2
 +
-+/*
-+ * Interval, in microseconds, between scoreboard maintenance.
-+ */
-+#ifndef SCOREBOARD_MAINTENANCE_INTERVAL
-+#define SCOREBOARD_MAINTENANCE_INTERVAL 1000000
-+#endif
++typedef struct ap_ctable {
++    pid_t pid;
++    unsigned char status;
++} ap_ctable;
 +
-+/* Number of requests to try to handle in a single process.  If <= 0,
-+ * the children don't die off.
-+ */
-+#ifndef DEFAULT_MAX_REQUESTS_PER_CHILD
-+#define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
-+#endif
++#endif /* APACHE_MPM_PERUSER_H */
+diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-peruser/server/mpm/experimental/peruser/peruser.c
+--- httpd-2.2.13/server/mpm/experimental/peruser/peruser.c	1970-01-01 03:00:00.000000000 +0300
++++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/peruser.c	2009-09-10 11:52:39.000000000 +0300
+@@ -0,0 +1,3884 @@
 +
-+#endif /* AP_MPM_DEFAULT_H */
-Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
-===================================================================
---- /dev/null
-+++ httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
-@@ -0,0 +1,3223 @@
 +/* ====================================================================
 + * The Apache Software License, Version 1.1
 + *
@@ -338,7 +425,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 + * University of Illinois, Urbana-Champaign.
 + */
 +
-+/* Peruser version 0.3.0 */
++/* Peruser version 0.4.0 */
 +
 +/* #define MPM_PERUSER_DEBUG */
 +
@@ -477,20 +564,30 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +
 +#define CHILD_STATUS_STANDBY  0  /* wait for a request before starting */
 +#define CHILD_STATUS_STARTING 1  /* wait for socket creation */
-+#define CHILD_STATUS_READY    2  /* wait for mux to restart */
-+#define CHILD_STATUS_ACTIVE   3  /* ready to take requests */
++#define CHILD_STATUS_READY    2  /* is ready to take requests */
++#define CHILD_STATUS_ACTIVE   3  /* is currently busy handling requests */
 +#define CHILD_STATUS_RESTART  4  /* child about to die and restart */
 +
++/* cgroup settings */
++#define CGROUP_TASKS_FILE "/tasks"
++#define CGROUP_TASKS_FILE_LEN 7
++
 +/* config globals */
 +
 +int ap_threads_per_child=0;         /* Worker threads per child */
 +static apr_proc_mutex_t *accept_mutex;
 +static int ap_min_processors=DEFAULT_MIN_PROCESSORS;
 +static int ap_min_free_processors=DEFAULT_MIN_FREE_PROCESSORS;
++static int ap_max_free_processors=DEFAULT_MAX_FREE_PROCESSORS;
 +static int ap_max_processors=DEFAULT_MAX_PROCESSORS;
++static int ap_min_multiplexers=DEFAULT_MIN_MULTIPLEXERS;
++static int ap_max_multiplexers=DEFAULT_MAX_MULTIPLEXERS;
 +static int ap_daemons_limit=0;      /* MaxClients */
-+static int expire_timeout=1800;
-+static int idle_timeout=900;
++static int expire_timeout=DEFAULT_EXPIRE_TIMEOUT;
++static int idle_timeout=DEFAULT_IDLE_TIMEOUT;
++static int multiplexer_idle_timeout=DEFAULT_MULTIPLEXER_IDLE_TIMEOUT;
++static int processor_wait_timeout=DEFAULT_PROCESSOR_WAIT_TIMEOUT;
++static int processor_wait_steps=DEFAULT_PROCESSOR_WAIT_STEPS;
 +static int server_limit = DEFAULT_SERVER_LIMIT;
 +static int first_server_limit;
 +static int changed_limit_at_restart;
@@ -504,19 +601,30 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +{
 +    int processor_id;
 +
++    const char *name;	/* Server environment's unique string identifier */
++
 +    /* security settings */
 +    uid_t uid;          /* user id */
 +    gid_t gid;          /* group id */
 +    const char *chroot; /* directory to chroot() to, can be null */
++    short nice_lvl;
++    const char *cgroup; /* cgroup directory, can be null */
 +
 +    /* resource settings */
 +    int min_processors;
 +    int min_free_processors;
++    int max_free_processors;
 +    int max_processors;
++    short availability;
 +
 +    /* sockets */
 +    int input;          /* The socket descriptor */
 +    int output;         /* The socket descriptor */
++
++    /* error flags */
++    /* we use these to reduce log clutter (report only on first failure) */
++    short error_cgroup; /* When writing pid to cgroup fails */
++    short error_pass;   /* When unable to pass request to the processor (eg all workers busy) */
 +} server_env_t;
 +
 +typedef struct
@@ -571,6 +679,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +typedef struct
 +{
 +    server_env_t *senv;
++    short missing_senv_reported;
 +} peruser_server_conf;
 +
 +
@@ -586,7 +695,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 + * process.
 + */
 +static apr_size_t child_info_size;
-+static child_info *child_info_image;
++static child_info *child_info_image = NULL;
 +static child_grace_info_t *child_grace_info_table;
 +struct ap_ctable *ap_child_table;
 +
@@ -653,6 +762,11 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +int grace_children = 0;
 +int grace_children_alive = 0;
 +int server_env_cleanup = 1;
++const char *multiplexer_chroot = NULL;
++
++// function added to mod_ssl and exported (there was nothing useful for us in the current api)
++typedef int (*ssl_server_is_https_t)(server_rec*);
++ssl_server_is_https_t ssl_server_is_https = NULL;
 +
 +#ifdef GPROF
 +/* 
@@ -719,6 +833,25 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    return "UNKNOWN";
 +}
 +
++char* scoreboard_status_string(int status) {
++    switch(status)
++    {
++        case SERVER_DEAD:  return "DEAD";
++        case SERVER_STARTING: return "STARTING";
++        case SERVER_READY:    return "READY";
++        case SERVER_BUSY_READ:   return "BUSY_READ";
++        case SERVER_BUSY_WRITE:   return "BUSY_WRITE";
++        case SERVER_BUSY_KEEPALIVE:   return "BUSY_KEEPALIVE";
++        case SERVER_BUSY_LOG:   return "BUSY_LOG";
++        case SERVER_BUSY_DNS:   return "BUSY_DNS";
++        case SERVER_CLOSING:   return "CLOSING";
++        case SERVER_GRACEFUL:   return "GRACEFUL";
++        case SERVER_NUM_STATUS:   return "NUM_STATUS";
++    }
++
++    return "UNKNOWN";
++}
++
 +void dump_child_table()
 +{
 +#ifdef MPM_PERUSER_DEBUG
@@ -750,10 +883,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +{
 +#ifdef MPM_PERUSER_DEBUG
 +  int x;
-+  _DBG("%-3s %-7s %-7s", "N", "INPUT", "OUTPUT");
++  _DBG("%-3s %-7s %-7s %-7s", "N", "INPUT", "OUTPUT", "CHROOT");
 +  for(x = 0; x < NUM_SENV; x++)
 +  {
-+    _DBG("%-3d %-7d %-7d", x, SENV[x].input, SENV[x].output);
++      _DBG("%-3d %-7d %-7d %-7s", x, SENV[x].input, SENV[x].output, SENV[x].chroot);
 +  }
 +#endif
 +}
@@ -793,10 +926,6 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +
 +static void accept_mutex_on(void)
 +{
-+/* for some reason this fails if we listen on the pipe_of_death.
-+   fortunately I don't think we currently need it */
-+
-+#if 0
 +    apr_status_t rv = apr_proc_mutex_lock(accept_mutex);
 +    if (rv != APR_SUCCESS) {
 +        const char *msg = "couldn't grab the accept mutex";
@@ -811,12 +940,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +            exit(APEXIT_CHILDFATAL);
 +        }
 +    }
-+#endif
 +}
 +
 +static void accept_mutex_off(void)
 +{
-+#if 0
 +    apr_status_t rv = apr_proc_mutex_unlock(accept_mutex);
 +    if (rv != APR_SUCCESS) {
 +        const char *msg = "couldn't release the accept mutex";
@@ -834,7 +961,6 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +            exit(APEXIT_CHILDFATAL);
 +        }
 +    }
-+#endif
 +}
 +
 +/* On some architectures it's safe to do unserialized accept()s in the single
@@ -997,8 +1123,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    ret = apr_socket_recv(lr->sd, &pipe_read_char, &n);
 +    if (APR_STATUS_IS_EAGAIN(ret))
 +    {
-+            /* It lost the lottery. It must continue to suffer
-+             * through a life of servitude. */
++       /* It lost the lottery. It must continue to suffer
++        * through a life of servitude. */
++       _DBG("POD read EAGAIN");
++       return ret;
 +    }
 +    else
 +    {
@@ -1136,6 +1264,109 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    return 0;
 +}
 +
++
++static int total_processors(int child_num)
++{
++    int i, total;
++
++    for(i = 0, total = 0; i < NUM_CHILDS; ++i)
++    {
++        if(CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv)
++            total++;
++    }
++
++    return total;
++}
++
++static int idle_processors(int child_num)
++{
++    int i, total;
++
++    for(i = 0, total = 0; i < NUM_CHILDS; ++i)
++    {
++        if(CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv &&
++           (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY))
++        {
++            total++;
++        }
++    }
++
++    return total;
++}
++
++static int wait_for_workers(child_info_t *processor) {
++    int i, wait_step_size, wait_time;
++    
++    wait_step_size = 100 / processor_wait_steps;
++
++    /*	Check if the processor is available */
++    if (total_processors(processor->id) == processor->senv->max_processors &&
++        idle_processors(processor->id) == 0 && processor_wait_timeout > 0) {
++        /* The processor is currently busy, try to wait (a little) */
++        _DBG("processor seems to be busy, trying to wait for it");
++
++        if (processor->senv->availability == 0) {
++            processor->senv->availability = 0;
++
++            _DBG("processor is very busy (availability = 0) - not passing request");
++
++            if (processor->senv->error_pass == 0) {
++                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
++                             "Too many requests for processor %s, increase MaxProcessors", processor->senv->name);
++            }
++	    
++            /* No point in waiting for the processor, it's very busy */
++            return -1;
++        }
++        
++        /* We sleep a little (depending how available the processor usually is) */
++        wait_time = (processor_wait_timeout / processor_wait_steps) * 1000000;
++
++        for(i = 0; i <= processor->senv->availability; i += wait_step_size) {
++            usleep(wait_time);
++
++            /* Check if the processor is ready */
++            if (total_processors(processor->id) < processor->senv->max_processors ||
++                idle_processors(processor->id) > 0) {
++                /* The processor has freed - lets use it */
++                _DBG("processor freed before wait time expired");
++                break;
++            }
++        }
++        
++        if (processor->senv->availability <= wait_step_size) {
++            processor->senv->availability = 0;
++        }
++        else processor->senv->availability -= wait_step_size;
++        
++        /* Check if we waited all the time */
++        if (i > processor->senv->availability) {
++            _DBG("processor is busy - not passing request (availability = %d)",
++                 processor->senv->availability);
++
++            if (processor->senv->error_pass == 0) {
++                ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
++                             "Too many requests for processor %s, increase MaxProcessors", processor->senv->name);
++            }
++
++            return -1;
++        }
++
++        /* We could increase the availability a little here,
++         * because the processor got freed eventually
++         */
++    }
++    else {
++        /* Smoothly increment the availability back to 100 */
++        if (processor->senv->availability >= 100-wait_step_size) {
++            processor->senv->availability = 100;
++        }
++        else processor->senv->availability += wait_step_size;
++    }
++
++    return 0;
++}
++
 +/*
 + * This function sends a raw socket over to a processor. It uses the same
 + * on-wire format as pass_request. The recipient can determine if he got
@@ -1161,6 +1392,9 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +                "(unkonwn)", my_child_num);
 +        return -1;
 +    }
++    
++    /* Make sure there are free workers on the other end */
++    if (wait_for_workers(processor) == -1) return -1;
 +
 +    _DBG("passing request to another child.", 0);
 +
@@ -1188,7 +1422,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    msg.msg_iovlen  = 5;
 +
 +    cmsg = apr_palloc(pool, sizeof(*cmsg) + sizeof(sock_fd));
-+    cmsg->cmsg_len   = sizeof(*cmsg) + sizeof(sock_fd);
++    cmsg->cmsg_len   = CMSG_LEN(sizeof(sock_fd));
 +    cmsg->cmsg_level = SOL_SOCKET;
 +    cmsg->cmsg_type  = SCM_RIGHTS;
 +
@@ -1235,6 +1469,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    child_info_t *processor;
 +    apr_pool_t *ptrans;
 +    peruser_server_conf *sconf;
++    int ssl_on;
 +
 +    _DBG("Creating dummy connection to use the vhost lookup api", 0);
 +
@@ -1243,39 +1478,65 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +                                            sbh, bucket_alloc);
 +    _DBG("Looking up the right vhost");
 +    if (current_conn) {
-+	    ap_update_vhost_given_ip(current_conn);
-+	    _DBG("Base server is %s, name based vhosts %s", current_conn->base_server->server_hostname,
-+		    current_conn->vhost_lookup_data ? "on" : "off");
++        ap_update_vhost_given_ip(current_conn);
++        _DBG("Base server is %s, name based vhosts %s", current_conn->base_server->server_hostname,
++             current_conn->vhost_lookup_data ? "on" : "off");
 +    }
 +
-+    if (current_conn && !current_conn->vhost_lookup_data && CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
-+    	_DBG("We are not using name based vhosts, we'll directly pass the socket.");
-+	
-+	sconf = PERUSER_SERVER_CONF(current_conn->base_server->module_config);
-+	processor = &CHILD_INFO_TABLE[sconf->senv->processor_id];
++    // check for ssl configuration for this server (ssl_server_is_https is NULL if we have no mod_ssl)
++    if(ssl_server_is_https) ssl_on = ssl_server_is_https(current_conn->base_server);
++    else ssl_on = 0;
 +
-+	_DBG("Forwarding without further inspection, processor %d", processor->id);
-+        if (processor->status == CHILD_STATUS_STANDBY)
-+        {
-+             _DBG("Activating child #%d", processor->id);
-+             processor->status = CHILD_STATUS_STARTING;
++    if (current_conn && (!current_conn->vhost_lookup_data || ssl_on) && CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
++    	_DBG("We are not using name based vhosts (or SSL is enabled), we'll directly pass the socket.");
++
++        sconf = PERUSER_SERVER_CONF(current_conn->base_server->module_config);
++
++        if (sconf->senv != NULL) {
++            processor = &CHILD_INFO_TABLE[sconf->senv->processor_id];
++
++            _DBG("Forwarding without further inspection, processor %d", processor->id);
++            if (processor->status == CHILD_STATUS_STANDBY)
++              {
++                  _DBG("Activating child #%d", processor->id);
++                  processor->status = CHILD_STATUS_STARTING;
++              }
++            
++            _DBG("Creating new pool",0);
++            apr_pool_create(&ptrans, pool);
++
++            _DBG("Passing request.",0);
++            if (pass_socket(sock, processor, ptrans) == -1) {
++                if (processor->senv->error_pass == 0) {
++                    ap_log_error(APLOG_MARK, APLOG_ERR, 0,
++                                 ap_server_conf, "Could not pass request to proper "                             
++                                 "child, request will not be honoured.");
++                }
++                
++                processor->senv->error_pass = 1;
++            }
++            else {
++                processor->senv->error_pass = 0;
++            }
 +        }
++        else {
++            _DBG("Base server has no senv set!");
 +
-+        _DBG("Creating new pool",0);
-+	apr_pool_create(&ptrans, pool);
-+        _DBG("Passing request.",0);
-+        if (pass_socket(sock, processor, ptrans) == -1)
-+        {
-+            ap_log_error(APLOG_MARK, APLOG_ERR, 0,
-+                  ap_server_conf, "Could not pass request to proper "                             
-+                  "child, request will not be honoured.");
-+             return;
++            if (sconf->missing_senv_reported == 0) {
++                ap_log_error(APLOG_MARK, APLOG_ERR, 0,
++                             ap_server_conf, "Virtualhost %s has no server environment set, "                             
++                             "request will not be honoured.", current_conn->base_server->server_hostname);
++            }
++
++            sconf->missing_senv_reported = 1;
 +        }
++
 +        if (current_conn)
 +        {
 +            _DBG("freeing connection",0);
 +            ap_lingering_close(current_conn);
 +        }
++
 +        _DBG("doing longjmp",0);
 +        longjmp(CHILD_INFO_TABLE[my_child_num].jmpbuffer, 1);
 +	return;
@@ -1286,9 +1547,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +        ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, "apr_os_sock_get");
 +    }
 +
-+    _DBG("child_num=%d sock=%ld sock_fd=%d\n", my_child_num, sock, sock_fd);
++    _DBG("child_num=%d sock=%ld sock_fd=%d", my_child_num, sock, sock_fd);
 +    _DBG("type=%s %d", child_type_string(CHILD_INFO_TABLE[my_child_num].type), my_child_num);
 +
++#ifdef _OSD_POSIX
 +    if (sock_fd >= FD_SETSIZE)
 +    {
 +        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
@@ -1300,6 +1562,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +        _DBG("child_num=%d: exiting with error", my_child_num);
 +        return;
 +    }
++#endif
 +
 +    if (CHILD_INFO_TABLE[my_child_num].sock_fd < 0)
 +    {
@@ -1349,36 +1612,6 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    return DECLINED;
 +}
 +
-+static int total_processors(int child_num)
-+{
-+    int i, total;
-+
-+    for(i = 0, total = 0; i < NUM_CHILDS; ++i)
-+    {
-+        if(CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv)
-+            total++;
-+    }
-+
-+    return total;
-+}
-+
-+static int idle_processors(int child_num)
-+{
-+    int i, total;
-+
-+    for(i = 0, total = 0; i < NUM_CHILDS; ++i)
-+    {
-+        if(CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv &&
-+           (SCOREBOARD_STATUS(i) == SERVER_STARTING ||
-+            SCOREBOARD_STATUS(i) == SERVER_READY))
-+        {
-+            total++;
-+        }
-+    }
-+
-+    return total;
-+}
-+
 +static int pass_request(request_rec *r, child_info_t *processor)
 +{
 +    int rv;
@@ -1419,10 +1652,13 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +      apr_table_get(r->headers_in, "Host"), my_child_num, processor->senv->output);
 +    _DBG("r->the_request=\"%s\" len=%d", r->the_request, strlen(r->the_request));
 +
-+    ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len);
++    /* Make sure there are free workers on the other end */
++    if (wait_for_workers(processor) == -1) return -1;
 +
++    ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len);
++    
 +    /* Scan the brigade looking for heap-buckets */
-+
++    
 +    _DBG("Scanning the brigade",0);
 +    bucket = APR_BRIGADE_FIRST(bb);
 +    while (bucket != APR_BRIGADE_SENTINEL(bb) &&
@@ -1490,7 +1726,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    msg.msg_iovlen  = 5;
 +
 +    cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sock_fd));
-+    cmsg->cmsg_len   = sizeof(*cmsg) + sizeof(sock_fd);
++    cmsg->cmsg_len   = CMSG_LEN(sizeof(sock_fd));
 +    cmsg->cmsg_level = SOL_SOCKET;
 +    cmsg->cmsg_type  = SCM_RIGHTS;
 +
@@ -1499,7 +1735,6 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    msg.msg_control    = cmsg;
 +    msg.msg_controllen = cmsg->cmsg_len;
 +
-+
 +    if (processor->status == CHILD_STATUS_STANDBY)
 +    {
 +        _DBG("Activating child #%d", processor->id);
@@ -1564,7 +1799,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    iov[3].iov_len  = HUGE_STRING_LEN;
 +
 +    cmsg = apr_palloc(ptrans, sizeof(*cmsg) + sizeof(trans_sock_fd));
-+    cmsg->cmsg_len = sizeof(*cmsg) + sizeof(trans_sock_fd);
++    cmsg->cmsg_len = CMSG_LEN(sizeof(trans_sock_fd));
 +
 +    msg.msg_name       = NULL;
 +    msg.msg_namelen    = 0;
@@ -1576,12 +1811,22 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    /* -- receive data from socket -- */
 +    apr_os_sock_get(&ctrl_sock_fd, lr->sd);
 +    _DBG("receiving from sock_fd=%d", ctrl_sock_fd);
-+    ret = recvmsg(ctrl_sock_fd, &msg, 0);
 +
-+    if(ret == -1)
-+      _DBG("recvmsg failed with error \"%s\"", strerror(errno));
-+    else
-+      _DBG("recvmsg returned %d", ret);
++    // Don't block
++    ret = recvmsg(ctrl_sock_fd, &msg, MSG_DONTWAIT);
++
++    if (ret == -1 && errno == EAGAIN) {
++        _DBG("receive_from_multiplexer recvmsg() EAGAIN, someone was faster");
++        
++        return APR_EAGAIN;
++    }
++    else if (ret == -1) {
++        _DBG("recvmsg failed with error \"%s\"", strerror(errno));
++        
++        // Error, better kill this child to be on the safe side
++        return APR_EGENERAL;
++    }
++    else _DBG("recvmsg returned %d", ret);
 +
 +    /* -- extract socket from the cmsg -- */
 +    memcpy(&trans_sock_fd, CMSG_DATA(cmsg), sizeof(trans_sock_fd));
@@ -1604,32 +1849,32 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    apr_cpystrn(headers, buff, header_len + 1);
 +    _DBG("header_len=%d headers=\"%s\"", header_len, headers);
 +
-+if (header_len) {    
-+    _DBG("header_len > 0, we got a request", 0);
-+    /* -- store received data into an brigade and add
-+          it to the current transaction's pool -- */
-+    bucket = apr_bucket_eos_create(alloc);
-+    APR_BRIGADE_INSERT_HEAD(bb, bucket);
-+    bucket = apr_bucket_socket_create(*trans_sock, alloc);
-+    APR_BRIGADE_INSERT_HEAD(bb, bucket);
-+
-+    if (body_len) {
-+        body = (char*)&buff[header_len + 1];
-+        _DBG("body_len=%d body=\"%s\"", body_len, body);
-+
-+        bucket = apr_bucket_heap_create(body, body_len, NULL, alloc);
++    if (header_len) {    
++        _DBG("header_len > 0, we got a request", 0);
++        /* -- store received data into an brigade and add
++           it to the current transaction's pool -- */
++        bucket = apr_bucket_eos_create(alloc);
++        APR_BRIGADE_INSERT_HEAD(bb, bucket);
++        bucket = apr_bucket_socket_create(*trans_sock, alloc);
++        APR_BRIGADE_INSERT_HEAD(bb, bucket);
++        
++        if (body_len) {
++            body = (char*)&buff[header_len + 1];
++            _DBG("body_len=%d body=\"%s\"", body_len, body);
++            
++            bucket = apr_bucket_heap_create(body, body_len, NULL, alloc);
++            APR_BRIGADE_INSERT_HEAD(bb, bucket);
++        } else {
++            _DBG("There is no body",0);
++        }
++        
++        bucket = apr_bucket_heap_create(headers, header_len, NULL, alloc);
++        
 +        APR_BRIGADE_INSERT_HEAD(bb, bucket);
++        apr_pool_userdata_set(bb, "PERUSER_SOCKETS", NULL, ptrans);
 +    } else {
-+        _DBG("There is no body",0);
++        _DBG("header_len == 0, we got a socket only", 0);
 +    }
-+
-+    bucket = apr_bucket_heap_create(headers, header_len, NULL, alloc);
-+
-+    APR_BRIGADE_INSERT_HEAD(bb, bucket);
-+    apr_pool_userdata_set(bb, "PERUSER_SOCKETS", NULL, ptrans);
-+} else {
-+    _DBG("header_len == 0, we got a socket only", 0);
-+}
 +    _DBG("returning 0", 0);
 +    return 0;
 +}
@@ -1681,26 +1926,90 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    return 0;
 +}
 +
-+static int peruser_setup_child(int childnum)
++static int peruser_setup_cgroup(int childnum, server_env_t *senv, apr_pool_t *pool)
++{
++    apr_file_t *file;
++    int length;
++    apr_size_t content_len;
++    char *tasks_file, *content, *pos;
++
++    _DBG("starting to add pid to cgroup %s", senv->cgroup);
++
++    length = strlen(senv->cgroup) + CGROUP_TASKS_FILE_LEN;
++    tasks_file = malloc(length);
++
++    if (!tasks_file) return -1;
++
++    pos = apr_cpystrn(tasks_file, senv->cgroup, length);
++    apr_cpystrn(pos, CGROUP_TASKS_FILE, CGROUP_TASKS_FILE_LEN);
++
++    /* Prepare the data to be written to tasks file */
++    content = apr_itoa(pool, ap_my_pid);
++    content_len  = strlen(content);
++
++    _DBG("writing pid %s to tasks file %s", content, tasks_file);
++
++    if (apr_file_open(&file, tasks_file, APR_WRITE, APR_OS_DEFAULT, pool)) {
++        if (senv->error_cgroup == 0) {
++            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
++                         "cgroup: unable to open file %s",
++                         tasks_file);
++        }
++
++        senv->error_cgroup = 1;
++        free(tasks_file);
++        return OK; /* don't fail if cgroup not available */
++    }
++
++    if (apr_file_write(file, content, &content_len)) {
++        if (senv->error_cgroup == 0) {
++            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
++                         "cgroup: unable to write pid to file %s",
++                         tasks_file);
++        }
++        senv->error_cgroup = 1;
++    }
++    else {
++        senv->error_cgroup = 0;
++    }
++
++    apr_file_close(file);
++
++    free(tasks_file);
++
++    return OK;
++}
++
++static int peruser_setup_child(int childnum, apr_pool_t *pool)
 +{
 +    server_env_t *senv = CHILD_INFO_TABLE[childnum].senv;
 +
-+    if(senv->chroot) {
-+      _DBG("chdir to %s", senv->chroot);
-+      if(chdir(senv->chroot)) {
-+        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
-+                     "chdir: unable to change to directory: %s",
-+                     senv->chroot);
-+        return -1;
-+      }
++    _DBG("function called");
++
++    if (senv->nice_lvl != 0) {
++        nice(senv->nice_lvl);
++    }
++
++    if(senv->chroot) {
++        _DBG("chdir to %s", senv->chroot);
++
++        if(chdir(senv->chroot)) {
++            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
++                         "chdir: unable to change to directory: %s",
++                         senv->chroot);
++            return -1;
++        }
++
++        if(chroot(senv->chroot)) {
++            ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
++                         "chroot: unable to chroot to directory: %s",
++                         senv->chroot);
++            return -1;
++        }
++    }
 +
-+      _DBG("chroot to %s", senv->chroot);
-+      if(chroot(senv->chroot)) {
-+        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
-+                     "chroot: unable to change root to: %s",
-+                     senv->chroot);
-+        return -1;
-+      }
++    if(senv->cgroup) {
++   	peruser_setup_cgroup(childnum, senv, pool);
 +    }
 +
 +    if (senv->uid == -1 && senv->gid == -1) {
@@ -1876,15 +2185,6 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    {
 +        case CHILD_TYPE_MULTIPLEXER:
 +            _DBG("MULTIPLEXER %d", my_child_num);
-+
-+            /* update status on processors that are ready to accept requests */
-+            _DBG("updating processor stati", 0);
-+            for(i = 0; i < NUM_CHILDS; ++i)
-+            {
-+                if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY)
-+                    CHILD_INFO_TABLE[i].status = CHILD_STATUS_ACTIVE;
-+            }
-+
 +            break;
 +
 +        case CHILD_TYPE_PROCESSOR:
@@ -1908,7 +2208,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    apr_os_sock_put(&pod_sock, &fd, pconf);
 +    listen_add(pconf, pod_sock, check_pipe_of_death);
 +
-+    if(peruser_setup_child(my_child_num) != 0)
++    if(peruser_setup_child(my_child_num, pchild) != 0)
 +        clean_child_exit(APEXIT_CHILDFATAL);
 +
 +    ap_run_child_init(pchild, ap_server_conf);
@@ -1952,14 +2252,19 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +	    clean_child_exit(0);
 +	}
 +
-+	(void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
++        (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
++
++        CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_READY;
++        _DBG("Child %d (%s) is now ready", my_child_num, child_type_string(CHILD_INFO_TABLE[my_child_num].type));
 +
 +	/*
 +	 * Wait for an acceptable connection to arrive.
 +	 */
 +
-+	/* Lock around "accept", if necessary */
-+	SAFE_ACCEPT(accept_mutex_on());
++        /* Lock around "accept", if necessary */
++        if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
++            SAFE_ACCEPT(accept_mutex_on());
++        }
 +
 +        if (num_listensocks == 1) {
 +            offset = 0;
@@ -2011,18 +2316,27 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +         * defer the exit
 +         */
 +        status = listensocks[offset].accept_func((void *)&sock, &listensocks[offset], ptrans);
-+        SAFE_ACCEPT(accept_mutex_off()); 	/* unlock after "accept" */
++
++        if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
++            SAFE_ACCEPT(accept_mutex_off()); 	/* unlock after "accept" */
++        }
 +
 +        if (status == APR_EGENERAL) {
 +            /* resource shortage or should-not-occur occured */
 +            clean_child_exit(1);
 +        }
-+        else if (status != APR_SUCCESS || die_now) {
++        else if (status != APR_SUCCESS || die_now || sock == NULL) {
 +            continue;
 +        }
 +
++        if (CHILD_INFO_TABLE[my_child_num].status == CHILD_STATUS_READY) {
++            CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_ACTIVE;
++            _DBG("Child %d (%s) is now active", my_child_num, child_type_string(CHILD_INFO_TABLE[my_child_num].type));
++        }
++
 +        if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_PROCESSOR ||
-+            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER)
++            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER ||
++            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER)
 +        {
 +          _DBG("CHECKING IF WE SHOULD CLONE A CHILD...");
 +
@@ -2036,8 +2350,11 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +
 +          if(total_processors(my_child_num) <
 +              CHILD_INFO_TABLE[my_child_num].senv->max_processors &&
-+            idle_processors(my_child_num) <=
-+              CHILD_INFO_TABLE[my_child_num].senv->min_free_processors)
++            (idle_processors(my_child_num) <=
++              CHILD_INFO_TABLE[my_child_num].senv->min_free_processors ||
++             total_processors(my_child_num) <
++              CHILD_INFO_TABLE[my_child_num].senv->min_processors
++            ))
 +          {
 +              _DBG("CLONING CHILD");
 +              child_clone();
@@ -2086,46 +2403,80 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    clean_child_exit(0);
 +}
 +
-+static server_env_t* senv_add(int uid, int gid, const char* chroot)
-+{
++static server_env_t* find_senv_by_name(const char *name) {
 +    int i;
-+    int socks[2];
 +
-+    _DBG("Searching for matching senv...");
++    if (name == NULL) return NULL;
++
++    _DBG("name=%s", name);
++
++    for(i = 0; i < NUM_SENV; i++)
++      {
++          if(SENV[i].name != NULL && !strcmp(SENV[i].name, name)) {
++              return &SENV[i];
++          }
++      }
++
++    return NULL;
++}
++
++static server_env_t* find_matching_senv(server_env_t* senv) {
++    int i;
++
++    _DBG("name=%s uid=%d gid=%d chroot=%s", senv->name, senv->uid, senv->gid, senv->chroot);
 +
 +    for(i = 0; i < NUM_SENV; i++)
-+    {
-+      if(SENV[i].uid == uid && SENV[i].gid == gid &&
-+         (SENV[i].chroot == NULL || !strcmp(SENV[i].chroot, chroot)))
 +      {
-+          _DBG("Found existing senv: %i", i);
-+          return &SENV[i];
++          if((senv->name != NULL && SENV[i].name != NULL && !strcmp(SENV[i].name, senv->name)) ||
++             (senv->name == NULL && SENV[i].uid == senv->uid && SENV[i].gid == senv->gid &&
++              (
++               (SENV[i].chroot == NULL && senv->chroot == NULL) ||
++               ((SENV[i].chroot != NULL || senv->chroot != NULL) && !strcmp(SENV[i].chroot, senv->chroot)))
++              )
++             ) {
++              return &SENV[i];
++          }
 +      }
++
++    return NULL;
++}
++
++static server_env_t* senv_add(server_env_t *senv)
++{
++    int socks[2];
++    server_env_t *old_senv;
++
++    _DBG("Searching for matching senv...");
++
++    old_senv = find_matching_senv(senv);
++
++    if (old_senv) {
++        _DBG("Found existing senv");
++        senv = old_senv;
++        return old_senv;
 +    }
 +
 +    if(NUM_SENV >= server_limit)
-+    {
-+      _DBG("server_limit reached!");
-+      return NULL;
-+    }
++      {
++          _DBG("server_limit reached!");
++          return NULL;
++      }
 +
 +    _DBG("Creating new senv");
 +
-+    SENV[NUM_SENV].uid = uid;
-+    SENV[NUM_SENV].gid = gid;
-+    SENV[NUM_SENV].chroot = chroot;
++    memcpy(&SENV[NUM_SENV], senv, sizeof(server_env_t));
 +
-+    SENV[NUM_SENV].min_processors = ap_min_processors;
-+    SENV[NUM_SENV].min_free_processors = ap_min_free_processors;
-+    SENV[NUM_SENV].max_processors = ap_max_processors;
++    SENV[NUM_SENV].availability = 100;
 +
 +    socketpair(PF_UNIX, SOCK_STREAM, 0, socks);
 +    SENV[NUM_SENV].input  = socks[0];
 +    SENV[NUM_SENV].output = socks[1];
 +
++    senv = &SENV[NUM_SENV];
 +    return &SENV[server_env_image->control->num++];
 +}
 +
++
 +static const char* child_clone()
 +{
 +    int i;
@@ -2140,8 +2491,8 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    
 +    if(i == NUM_CHILDS && NUM_CHILDS >= server_limit)
 +    {
-+        _DBG("Trying to use more child ID's than NumServers.  "
-+               "Increase NumServers in your config file.");
++        _DBG("Trying to use more child ID's than ServerLimit.  "
++               "Increase ServerLimit in your config file.");
 +        return NULL;
 +    }    
 +
@@ -2151,7 +2502,14 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    new = &CHILD_INFO_TABLE[i];
 +
 +    new->senv = this->senv;
-+    new->type = CHILD_TYPE_WORKER;
++
++    if (this->type == CHILD_TYPE_MULTIPLEXER) {
++        new->type = CHILD_TYPE_MULTIPLEXER;
++    }
++    else {
++        new->type = CHILD_TYPE_WORKER;
++    }
++
 +    new->sock_fd = this->sock_fd;
 +    new->status = CHILD_STATUS_STARTING;
 +
@@ -2160,25 +2518,25 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +}
 +
 +static const char* child_add(int type, int status,
-+                             apr_pool_t *pool, uid_t uid, gid_t gid, const char* chroot)
++                             apr_pool_t *pool, server_env_t *senv)
 +{
 +    _DBG("adding child #%d", NUM_CHILDS);
 +
 +    if(NUM_CHILDS >= server_limit)
 +    {
-+        return "Trying to use more child ID's than NumServers.  "
-+               "Increase NumServers in your config file.";
++        return "Trying to use more child ID's than ServerLimit.  "
++               "Increase ServerLimit in your config file.";
 +    }
 +
-+       if (chroot && !ap_is_directory(pool, chroot))
-+               return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", chroot);
++       if (senv->chroot && !ap_is_directory(pool, senv->chroot))
++               return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", senv->chroot);
 +
-+    CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(uid, gid, chroot);
++    CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(senv);
 +
 +    if(CHILD_INFO_TABLE[NUM_CHILDS].senv == NULL)
 +    {
-+        return "Trying to use more server environments than NumServers.  "
-+               "Increase NumServers in your config file.";
++        return "Trying to use more server environments than ServerLimit.  "
++               "Increase ServerLimit in your config file.";
 +    }
 +
 +    if(type != CHILD_TYPE_WORKER)
@@ -2189,10 +2547,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    CHILD_INFO_TABLE[NUM_CHILDS].status = status;
 +
 +    _DBG("[%d] uid=%d gid=%d type=%d chroot=%s",
-+         NUM_CHILDS, uid, gid, type,
-+         chroot);
++         NUM_CHILDS, senv->uid, senv->gid, type,
++         senv->chroot);
 +
-+    if (uid == 0 || gid == 0)
++    if (senv->uid == 0 || senv->gid == 0)
 +    {
 +        _DBG("Assigning root user/group to a child.", 0);
 +    }
@@ -2239,7 +2597,7 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING,
 +                                               (request_rec *) NULL);
 +
-+    CHILD_INFO_TABLE[slot].status = CHILD_STATUS_ACTIVE;
++    CHILD_INFO_TABLE[slot].status = CHILD_STATUS_READY;
 +
 +
 +#ifdef _OSD_POSIX
@@ -2344,19 +2702,31 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +        if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING)
 +          make_child(ap_server_conf, i);
 +      }
-+      else if(((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR || 
-+               CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)  &&
-+               ap_scoreboard_image->parent[i].pid > 1) &&
-+               (idle_processors (i) > 1 || total_processes (i) == 1) && (
-+                   (expire_timeout > 0 &&  ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && 
-+                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) ||
-+                   (idle_timeout >   0 &&  ap_scoreboard_image->servers[i][0].status == SERVER_READY &&  
-+                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout)))
++      else if(
++    	      (((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR ||
++                 CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)  &&
++                ap_scoreboard_image->parent[i].pid > 1) &&
++               (idle_processors (i) > CHILD_INFO_TABLE[i].senv->min_free_processors || CHILD_INFO_TABLE[i].senv->min_free_processors == 0) &&
++               total_processes (i) > CHILD_INFO_TABLE[i].senv->min_processors && 
++               (
++                (expire_timeout > 0 &&  ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && 
++                 apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) ||
++                (idle_timeout >   0 &&  ap_scoreboard_image->servers[i][0].status == SERVER_READY &&  
++                 apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout) ||
++                (CHILD_INFO_TABLE[i].senv->max_free_processors > 0 && CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY &&
++                 idle_processors(i) > CHILD_INFO_TABLE[i].senv->max_free_processors))
++               )
++              || (CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER &&
++                  (multiplexer_idle_timeout > 0 && ap_scoreboard_image->servers[i][0].status == SERVER_READY &&
++                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > multiplexer_idle_timeout) &&
++                  total_processors(i) > CHILD_INFO_TABLE[i].senv->min_processors
++                  )
++            )
 +      {
 +        CHILD_INFO_TABLE[i].pid = 0;
 +        CHILD_INFO_TABLE[i].status = CHILD_STATUS_STANDBY;
 +
-+        if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)
++        if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER || CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER)
 +        {
 +          /* completely free up this slot */
 +
@@ -2455,7 +2825,6 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +        return 1;
 +    }
 +
-+#if 0
 +#if APR_USE_SYSVSEM_SERIALIZE
 +    if (ap_accept_lock_mech == APR_LOCK_DEFAULT || 
 +        ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
@@ -2471,7 +2840,6 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +            return 1;
 +        }
 +    }
-+#endif
 +
 +    if (!is_graceful) {
 +        if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
@@ -2677,6 +3045,12 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    ++ap_my_generation;
 +    ap_scoreboard_image->global->running_generation = ap_my_generation;
 +    
++    /* cleanup sockets */
++    for (i = 0; i < NUM_SENV; i++) {
++        close(SENV[i].input);
++        close(SENV[i].output);
++    }
++
 +    if (is_graceful) {
 +        char char_of_death = AP_PERUSER_CHAR_OF_DEATH;
 +
@@ -2765,14 +3139,6 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +        }
 +        _DBG("Total children of %d leaving behind for graceful restart (%d living)", 
 +                       grace_children, grace_children_alive);
-+
-+       /* destroy server_env_image */
-+        for (i = 0; i < NUM_SENV; i++)
-+        {
-+            close(SENV[i].input);
-+            close(SENV[i].output);
-+        }
-+       cleanup_server_environments(NULL);
 +    }
 +    else {
 +	/* Kill 'em off */
@@ -2792,6 +3158,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +{
 +    peruser_server_conf *c = (peruser_server_conf *)
 +                                  apr_pcalloc(p, sizeof(peruser_server_conf));
++
++    c->senv = NULL;
++    c->missing_senv_reported = 0;
++
 +    return c;
 +}
 +
@@ -2880,7 +3250,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    ap_listen_pre_config();
 +    ap_min_processors = DEFAULT_MIN_PROCESSORS;
 +    ap_min_free_processors = DEFAULT_MIN_FREE_PROCESSORS;
++    ap_max_free_processors = DEFAULT_MAX_FREE_PROCESSORS;
 +    ap_max_processors = DEFAULT_MAX_PROCESSORS;
++    ap_min_multiplexers = DEFAULT_MIN_MULTIPLEXERS;
++    ap_max_multiplexers = DEFAULT_MAX_MULTIPLEXERS;
 +    ap_daemons_limit = server_limit;
 +    ap_pid_fname = DEFAULT_PIDLOG;
 +    ap_lock_fname = DEFAULT_LOCKFILE;
@@ -2890,6 +3263,13 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +	ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
 +#endif
 +
++    expire_timeout = DEFAULT_EXPIRE_TIMEOUT;
++    idle_timeout = DEFAULT_IDLE_TIMEOUT;
++    multiplexer_idle_timeout = DEFAULT_MULTIPLEXER_IDLE_TIMEOUT;
++    processor_wait_timeout = DEFAULT_PROCESSOR_WAIT_TIMEOUT;
++    processor_wait_steps = DEFAULT_PROCESSOR_WAIT_STEPS;
++
++
 +    apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
 +
 +    /* we need to know ServerLimit and ThreadLimit before we start processing
@@ -2920,40 +3300,41 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +        return rv;
 +    }
 +
++    if (!child_info_image) {
++        _DBG("Initializing child_info_table", 0);
++        child_info_size = tmp_server_limit * sizeof(child_info_t) + sizeof(apr_size_t);
 +
-+    _DBG("Initializing child_info_table", 0);
-+    child_info_size = tmp_server_limit * sizeof(child_info_t) + sizeof(apr_size_t);
++        rv = apr_shm_create(&child_info_shm, child_info_size, NULL, global_pool);
 +
-+    rv = apr_shm_create(&child_info_shm, child_info_size, NULL, global_pool);
++        /*  if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) { */
++        if (rv != APR_SUCCESS) {
++            _DBG("shared memory creation failed", 0);
 +
-+/*  if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) { */
-+    if (rv != APR_SUCCESS) {
-+        _DBG("shared memory creation failed", 0);
++            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
++                         "Unable to create shared memory segment "
++                         "(anonymous shared memory failure)");
++        }
++        else if (rv == APR_ENOTIMPL) {
++            _DBG("anonymous shared memory not available", 0);
++            /* TODO: make up a filename and do name-based shmem */
++        }
 +
-+        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
-+                     "Unable to create shared memory segment "
-+                     "(anonymous shared memory failure)");
-+    }
-+    else if (rv == APR_ENOTIMPL) {
-+        _DBG("anonymous shared memory not available", 0);
-+        /* TODO: make up a filename and do name-based shmem */
-+    }
++        if (rv || !(shmem = apr_shm_baseaddr_get(child_info_shm))) {
++            _DBG("apr_shm_baseaddr_get() failed", 0);
++            return HTTP_INTERNAL_SERVER_ERROR;
++        }
 +
-+    if (rv || !(shmem = apr_shm_baseaddr_get(child_info_shm))) {
-+        _DBG("apr_shm_baseaddr_get() failed", 0);
-+        return HTTP_INTERNAL_SERVER_ERROR;
++        memset(shmem, 0, child_info_size);
++        child_info_image = (child_info*)apr_palloc(global_pool, sizeof(child_info));
++        child_info_image->control = (child_info_control*)shmem;
++        shmem += sizeof(child_info_control);
++        child_info_image->table = (child_info_t*)shmem;
 +    }
 +
-+    memset(shmem, 0, sizeof(child_info_size));
-+    child_info_image = (child_info*)calloc(1, sizeof(child_info_size));
-+    child_info_image->control = (child_info_control*)shmem;
-+    shmem += sizeof(child_info_control*);
-+    child_info_image->table = (child_info_t*)shmem;
-+
++    _DBG("Clearing child_info_table");
 +    child_info_image->control->num = 0;
 +
-+    for (i = 0; i < tmp_server_limit; i++)
-+    {
++    for (i = 0; i < tmp_server_limit; i++) {
 +        CHILD_INFO_TABLE[i].pid     = 0;
 +        CHILD_INFO_TABLE[i].senv    = (server_env_t*)NULL;
 +        CHILD_INFO_TABLE[i].type    = CHILD_TYPE_UNKNOWN;
@@ -2986,23 +3367,25 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +            return HTTP_INTERNAL_SERVER_ERROR;
 +        }
 +
-+        memset(shmem, 0, sizeof(server_env_size));
-+        server_env_image = (server_env*)calloc(1, sizeof(server_env_size));
++        memset(shmem, 0, server_env_size);
++        server_env_image = (server_env*)apr_palloc(global_pool, sizeof(server_env));
 +        server_env_image->control = (server_env_control*)shmem;
-+        shmem += sizeof(server_env_control*);
++        shmem += sizeof(server_env_control);
 +        server_env_image->table = (server_env_t*)shmem;
-+
-+        server_env_image->control->num = 0;
-+
-+        for (i = 0; i < tmp_server_limit; i++)
-+        {
-+            SENV[i].processor_id = -1;
-+            SENV[i].uid          = -1;
-+            SENV[i].gid          = -1;
-+            SENV[i].chroot       = NULL;
-+            SENV[i].input        = -1;
-+            SENV[i].output       = -1;
-+        }
++    }
++    
++    _DBG("Clearing server environment table");
++    server_env_image->control->num = 0;    
++
++    for (i = 0; i < tmp_server_limit; i++) {
++        SENV[i].processor_id = -1;
++        SENV[i].uid          = -1;
++        SENV[i].gid          = -1;
++        SENV[i].chroot       = NULL;
++        SENV[i].input        = -1;
++        SENV[i].output       = -1;
++        SENV[i].error_cgroup = 0;
++        SENV[i].error_pass   = 0;
 +    }
 +
 +    return OK;
@@ -3010,16 +3393,59 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +
 +static int peruser_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *server_list)
 +{
++    server_env_t senv;
++    const char *r;
++
 +    ap_child_table = (ap_ctable *)apr_pcalloc(p, server_limit * sizeof(ap_ctable));
 +
++    /* Retrieve the function from mod_ssl for detecting SSL virtualhosts */
++    ssl_server_is_https = (ssl_server_is_https_t) apr_dynamic_fn_retrieve("ssl_server_is_https");
++
++    /* Create the server environment for multiplexers */
++    senv.uid = unixd_config.user_id;
++    senv.gid = unixd_config.group_id;
++    senv.chroot = multiplexer_chroot;
++    senv.cgroup = NULL;
++    senv.nice_lvl = 0;
++    senv.name = NULL;
++
++    senv.min_processors 	= ap_min_multiplexers;
++    senv.min_free_processors 	= ap_min_free_processors;
++    senv.max_free_processors    = ap_max_free_processors;
++    senv.max_processors 	= ap_max_multiplexers;
++
++    r = child_add(CHILD_TYPE_MULTIPLEXER, CHILD_STATUS_STARTING,
++                     p, &senv);
++
++    if (r != NULL) {
++        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, p, r);
++        return -1;
++    }
++
 +    return OK;
 +}
 +
 +static int peruser_post_read(request_rec *r)
 +{
++    _DBG("function entered");
++
 +    peruser_server_conf *sconf = PERUSER_SERVER_CONF(r->server->module_config);
 +    child_info_t *processor;
 +
++    if (sconf->senv == NULL) {
++        _DBG("Server environment not set on virtualhost %s", r->server->server_hostname);
++
++        if (sconf->missing_senv_reported == 0) {
++            ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
++                         "Virtualhost %s has no server environment set, "
++                         "request will not be honoured.", r->server->server_hostname);
++        }
++        
++        sconf->missing_senv_reported = 1;
++
++        return HTTP_INTERNAL_SERVER_ERROR;
++    }
++
 +    if(CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER)
 +        processor = &CHILD_INFO_TABLE[sconf->senv->processor_id];
 +    else
@@ -3062,15 +3488,24 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +                _DBG("Passing request.",0);
 +                if (pass_request(r, processor) == -1)
 +                {
-+                    ap_log_error(APLOG_MARK, APLOG_ERR, 0,
-+                             ap_server_conf, "Could not pass request to proper "                             "child, request will not be honoured.");
-+                    return DECLINED;
++                    if (processor->senv->error_pass == 0) {
++                        ap_log_error(APLOG_MARK, APLOG_ERR, 0,
++                                     ap_server_conf, "Could not pass request to processor %s (virtualhost %s), request will not be honoured.",
++                                     processor->senv->name, r->hostname);
++                    }
++
++                    processor->senv->error_pass = 1;
++
++                    return HTTP_SERVICE_UNAVAILABLE;
++                }
++                else {
++                    processor->senv->error_pass = 0;
 +                }
++
 +                _DBG("doing longjmp",0);
 +                longjmp(CHILD_INFO_TABLE[my_child_num].jmpbuffer, 1);
 +                _DBG("request declined at our site",0);
 +                return DECLINED;
-+                _DBG("OUH! we should never reach this point",0);
 +            }
 +            _DBG("WTF: the server is assigned to the multiplexer! ... dropping request",0);
 +            return DECLINED;
@@ -3141,32 +3576,37 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    ap_rputs("<hr>\n", r);
 +    ap_rputs("<h2>peruser status</h2>\n", r);
 +    ap_rputs("<table border=\"0\">\n", r);
-+    ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>TYPE</td><td>UID</td>"
-+                   "<td>GID</td><td>CHROOT</td><td>INPUT</td>"
++    ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>SB STATUS</td><td>TYPE</td><td>UID</td>"
++                   "<td>GID</td><td>CHROOT</td><td>NICE</td><td>INPUT</td>"
 +                   "<td>OUTPUT</td><td>SOCK_FD</td>"
 +                   "<td>TOTAL PROCESSORS</td><td>MAX PROCESSORS</td>"
-+                   "<td>IDLE PROCESSORS</td><td>MIN FREE PROCESSORS</td></tr>\n", r);
++                   "<td>IDLE PROCESSORS</td><td>MIN FREE PROCESSORS</td>"
++                   "<td>AVAIL</td>"
++                   "</tr>\n", r);
 +    for (x = 0; x < NUM_CHILDS; x++)
 +        {
 +        senv = CHILD_INFO_TABLE[x].senv;
-+        ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%12s</td>"
-+                       "<td>%4d</td><td>%4d</td><td>%25s</td><td>%5d</td>"
++        ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%8s</td><td>%12s</td>"
++                       "<td>%4d</td><td>%4d</td><td>%25s</td><td>%3d</td><td>%5d</td>"
 +                       "<td>%6d</td><td>%7d</td><td>%d</td><td>%d</td>"
-+                       "<td>%d</td><td>%d</td></tr>\n", 
++                       "<td>%d</td><td>%d</td><td>%3d</td></tr>\n",
 +                       CHILD_INFO_TABLE[x].id, 
 +                       CHILD_INFO_TABLE[x].pid, 
 +                       child_status_string(CHILD_INFO_TABLE[x].status), 
++                       scoreboard_status_string(SCOREBOARD_STATUS(x)),
 +                       child_type_string(CHILD_INFO_TABLE[x].type), 
 +                       senv == NULL ? -1 : senv->uid, 
 +                       senv == NULL ? -1 : senv->gid, 
 +                       senv == NULL ? NULL : senv->chroot, 
++                       senv == NULL ? 0 : senv->nice_lvl,
 +                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->input, 
 +                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->output, 
 +                       CHILD_INFO_TABLE[x].sock_fd,
 +                       total_processors(x), 
 +                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->max_processors,
 +                       idle_processors(x),
-+                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors
++                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors,
++                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->availability
 +                       );
 +       }
 +    ap_rputs("</table>\n", r);
@@ -3220,50 +3660,234 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    APR_OPTIONAL_HOOK(ap, status_hook, peruser_status_hook, NULL, NULL, APR_HOOK_MIDDLE);
 +}
 +
-+/* we define an Processor w/ specific uid/gid */
-+static const char *cf_Processor(cmd_parms *cmd, void *dummy,
-+    const char *user_name, const char *group_name, const char *chroot)
++void senv_init(server_env_t * senv) {
++    senv->nice_lvl 		= 0;
++    senv->chroot 		= NULL;
++    senv->cgroup		= NULL;
++    senv->min_processors 	= ap_min_processors;
++    senv->min_free_processors 	= ap_min_free_processors;
++    senv->max_free_processors   = ap_max_free_processors;
++    senv->max_processors 	= ap_max_processors;
++}
++
++static const char *cf_Processor(cmd_parms *cmd, void *dummy, const char *arg)
 +{
-+    uid_t uid = ap_uname2id(user_name);
-+    gid_t gid = ap_gname2id(group_name);
++    const char *user_name = NULL, *group_name = NULL, *directive;
++    server_env_t senv;
++    ap_directive_t *current;
++
++    const char *endp = ap_strrchr_c(arg, '>');
++
++    if (endp == NULL) {
++	return apr_psprintf(cmd->temp_pool,
++			    "Error: Directive %s> missing closing '>'", cmd->cmd->name);
++    }
++
++    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
++
++    if (!arg) {
++   	return apr_psprintf(cmd->temp_pool,
++                            "Error: %s> must specify a processor name", cmd->cmd->name);
++    }
++
++    senv.name = ap_getword_conf(cmd->pool, &arg);
++    _DBG("processor_name: %s", senv.name);
++
++    if (strlen(senv.name) == 0) {
++        return apr_psprintf(cmd->temp_pool,
++                            "Error: Directive %s> takes one argument", cmd->cmd->name);
++    }
++
++    server_env_t *old_senv = find_senv_by_name(senv.name);
++
++    if (old_senv) {
++        return apr_psprintf(cmd->temp_pool,
++                            "Error: Processor %s already defined", senv.name);
++    }
 +
-+    _DBG("user=%s:%d group=%s:%d chroot=%s",
-+        user_name, uid, group_name, gid, chroot);
++    senv_init(&senv);
++
++    current = cmd->directive->first_child;
++
++    int proc_temp = 0;
++    for(; current != NULL; current = current->next) {
++        directive = current->directive;
++        
++        if (!strcasecmp(directive, "user")) {
++            user_name = current->args;
++        }
++        else if (!strcasecmp(directive, "group")) {
++   	    group_name = current->args;
++        }
++        else if (!strcasecmp(directive, "chroot")) {
++            senv.chroot = ap_getword_conf(cmd->pool, &current->args);
++        }
++        else if (!strcasecmp(directive, "nicelevel")) {
++    	    senv.nice_lvl = atoi(current->args);
++        }
++        else if (!strcasecmp(directive, "maxprocessors")) {
++            proc_temp = atoi(current->args);
++
++            if (proc_temp < 1) {
++                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                             "WARNING: Require MaxProcessors > 0, setting to 1");
++                proc_temp = 1;
++            }
++
++            senv.max_processors = proc_temp;
++        }
++        else if (!strcasecmp(directive, "minprocessors")) {
++            proc_temp = atoi(current->args);
++
++            if (proc_temp < 0) {
++                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                             "WARNING: Require MinProcessors >= 0, setting to 0");
++                proc_temp = 0;
++            }
++
++            senv.min_processors = proc_temp;
++        }
++        else if (!strcasecmp(directive, "minspareprocessors")) {
++            proc_temp = atoi(current->args);
++
++            if (proc_temp < 0) {
++                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                             "WARNING: Require MinSpareProcessors >= 0, setting to 0");
++                proc_temp = 0;
++            }
++
++            senv.min_free_processors = proc_temp;
++        }
++        else if (!strcasecmp(directive, "maxspareprocessors")) {
++            proc_temp = atoi(current->args);
++            
++            if (proc_temp < 0) {
++                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                             "WARNING: Require MaxSpareProcessors >= 0, setting to 0");
++                proc_temp = 0;
++            }
++
++            senv.max_free_processors = proc_temp;
++        }
++        else if (!strcasecmp(directive, "cgroup")) {
++            senv.cgroup = ap_getword_conf(cmd->pool, &current->args);
++        }
++        else {
++            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                         "Unknown directive %s in %s>", directive, cmd->cmd->name);
++        }
++    }
++
++    if (user_name == NULL || group_name == NULL) {
++        return apr_psprintf(cmd->temp_pool,
++                            "Error: User or Group must be set in %s>", cmd->cmd->name);
++    }
++
++    senv.uid = ap_uname2id(user_name);
++    senv.gid = ap_gname2id(group_name);
++
++    _DBG("name=%s user=%s:%d group=%s:%d chroot=%s nice_lvl=%d",
++         senv.name, user_name, senv.uid, group_name, senv.gid, senv.chroot, senv.nice_lvl);
++
++    _DBG("min_processors=%d min_free_processors=%d max_spare_processors=%d max_processors=%d",
++         senv.min_processors, senv.min_free_processors, senv.max_free_processors, senv.max_processors);
 +
 +    return child_add(CHILD_TYPE_PROCESSOR, CHILD_STATUS_STANDBY,
-+                     cmd->pool, uid, gid, chroot);
++                     cmd->pool, &senv);
++}
++
++static const char *cf_Processor_depr(cmd_parms *cmd, void *dummy,
++    const char *user_name, const char *group_name, const char *chroot)
++{
++    return NULL;
 +}
 +
 +/* we define an Multiplexer child w/ specific uid/gid */
 +static const char *cf_Multiplexer(cmd_parms *cmd, void *dummy,
 +    const char *user_name, const char *group_name, const char *chroot)
 +{
-+    uid_t uid = ap_uname2id(user_name);
-+    gid_t gid = ap_gname2id(group_name);
++    static short depr_warned = 0;
++    
++    if (depr_warned == 0) {
++        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                     "WARNING: Multiplexer directive is deprecated. Multiplexer user and group is set by User and Group directives.");    
++        
++        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                     "To set multiplexer chroot, please use MultiplexerChroot.");
++
++        depr_warned = 1;
++    }
++
++    if (chroot) {
++        if (!ap_is_directory(cmd->pool, chroot))
++            return apr_psprintf(cmd->pool, "Error: multiplexer chroot directory [%s] does not exist", chroot);
 +
-+    _DBG("user=%s:%d group=%s:%d chroot=%s [multiplexer id %d]",
-+        user_name, uid, group_name, gid, chroot, NUM_CHILDS);
++        multiplexer_chroot = chroot;
++        _DBG("Setting multiplexer chroot to %s", chroot);
++    }
 +
-+    return child_add(CHILD_TYPE_MULTIPLEXER, CHILD_STATUS_STARTING,
-+                     cmd->pool, uid, gid, chroot);
++    return NULL;
 +}
 +
-+static const char* cf_ServerEnvironment(cmd_parms *cmd, void *dummy,
-+    const char *user_name, const char *group_name, const char *chroot)
++static const char* cf_MultiplexerChroot(cmd_parms *cmd, void *dummy,
++                                         const char *path)
 +{
-+    int uid = ap_uname2id(user_name);
-+    int gid = ap_gname2id(group_name);
-+    peruser_server_conf *sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
++    multiplexer_chroot = path;
 +
-+    _DBG("function entered", 0);
++    if (path && !ap_is_directory(cmd->pool, path))
++        return apr_psprintf(cmd->pool, "Error: multiplexer chroot directory [%s] does not exist", path);
 +
-+       if (chroot && !ap_is_directory(cmd->pool, chroot))
-+               return apr_psprintf(cmd->pool, "Error: chroot directory [%s] does not exist", chroot);
++    _DBG("setting multiplexer chroot to %s", path);
++
++    return NULL;
++}
 +
-+    sconf->senv = senv_add(uid, gid, chroot);
++static const char* cf_ServerEnvironment(cmd_parms *cmd, void *dummy,
++    const char *name, const char * group_name, const char * chroot)
++{
++    peruser_server_conf *sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
++    server_env_t senv;
++    char * processor_name, *tmp;
++	
++    _DBG("function entered", 0);
++	
++    /* name of processor env */
++    processor_name = name;
++    
++    if(group_name != NULL || chroot != NULL) {
++        /* deprecated ServerEnvironment user group chroot syntax
++         * we create simple server env based on user/group/chroot only
++         */
++        processor_name = apr_pstrcat(cmd->pool, name, "_",group_name, "_", chroot, NULL);
++	
++        /* search for previous default server env */
++        sconf->senv = find_senv_by_name(processor_name);
++	
++        if(!sconf->senv) {
++            senv_init(&senv);
++            senv.uid = ap_uname2id(name);
++            senv.gid = ap_gname2id(group_name);
++            senv.chroot = chroot;
++            senv.name = processor_name;
++            
++            tmp = child_add(CHILD_TYPE_PROCESSOR, CHILD_STATUS_STANDBY, cmd->pool, &senv);
++            /* error handling in case this child can't be created */
++            if(tmp)
++                return tmp;
++        }
++    }
++    
++    /* use predefined processor environment or default named "user_group_chroot" */
++    if(sconf->senv == NULL)
++        sconf->senv = find_senv_by_name(processor_name);
++    
++    if (sconf->senv == NULL) {
++        return apr_psprintf(cmd->pool,
++                            "Error: Processor %s not defined", name);
++    }
 +
-+    _DBG("user=%s:%d group=%s:%d chroot=%s numchilds=%d",
-+        user_name, uid, group_name, gid, chroot, NUM_CHILDS);
++    _DBG("user=%d group=%d chroot=%s numchilds=%d",
++        sconf->senv->uid, sconf->senv->gid, sconf->senv->chroot, NUM_CHILDS);
 +
 +    return NULL;
 +}
@@ -3328,10 +3952,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +
 +    min_procs = atoi(arg);
 +
-+    if (min_procs < 1) {
++    if (min_procs < 0) {
 +        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                     "WARNING: Require MaxProcessors > 0, setting to 1");
-+        min_procs = 1;
++                     "WARNING: Require MinProcessors >= 0, setting to 0");
++        min_procs = 0;
 +    }
 +
 +    if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
@@ -3357,10 +3981,10 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +
 +    min_free_procs = atoi(arg);
 +
-+    if (min_free_procs < 1) {
++    if (min_free_procs < 0) {
 +        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                     "WARNING: Require MinSpareProcessors > 0, setting to 1");
-+        min_free_procs = 1;
++                     "WARNING: Require MinSpareProcessors >= 0, setting to 0");
++        min_free_procs = 0;
 +    }
 +
 +    if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
@@ -3374,6 +3998,35 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    return NULL;
 +}
 +
++static const char *set_max_free_processors (cmd_parms *cmd, void *dummy, const char *arg)
++{
++     peruser_server_conf *sconf;
++     int max_free_procs;
++     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
++
++     if (err != NULL) {
++         return err;
++     }
++
++     max_free_procs = atoi(arg);
++
++     if (max_free_procs < 0) {
++         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                      "WARNING: Require MaxSpareProcessors >= 0, setting to 0");
++         max_free_procs = 0;
++     }
++
++     if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
++         sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
++         sconf->senv->max_free_processors = max_free_procs;
++     }
++     else {
++         ap_max_free_processors = max_free_procs;
++     }
++
++     return NULL;
++}
++
 +static const char *set_max_processors (cmd_parms *cmd, void *dummy, const char *arg)
 +{
 +    peruser_server_conf *sconf;
@@ -3403,6 +4056,50 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    return NULL;
 +}
 +
++static const char *set_min_multiplexers (cmd_parms *cmd, void *dummy, const char *arg)
++{
++    int min_multiplexers;
++    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
++
++    if (err != NULL) {
++        return err;
++    }
++
++    min_multiplexers = atoi(arg);
++
++    if (min_multiplexers < 1) {
++        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                     "WARNING: Require MinMultiplexers > 0, setting to 1");
++        min_multiplexers = 1;
++    }
++
++    ap_min_multiplexers = min_multiplexers;
++
++    return NULL;
++}
++
++static const char *set_max_multiplexers (cmd_parms *cmd, void *dummy, const char *arg)
++{
++    int max_multiplexers;
++    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
++
++    if (err != NULL) {
++        return err;
++    }
++
++    max_multiplexers = atoi(arg);
++
++    if (max_multiplexers < 1) {
++        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                     "WARNING: Require MaxMultiplexers > 0, setting to 1");
++        max_multiplexers = 1;
++    }
++
++    ap_max_multiplexers = max_multiplexers;
++
++    return NULL;
++}
++
 +static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) 
 +{
 +    int tmp_server_limit;
@@ -3465,6 +4162,42 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +    return NULL;
 +}
 +
++static const char *set_multiplexer_idle_timeout (cmd_parms *cmd, void *dummy, const char *arg) {
++    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
++
++    if (err != NULL) {
++        return err;
++    }
++
++    multiplexer_idle_timeout = atoi(arg);
++
++    return NULL;
++}
++
++static const char *set_processor_wait_timeout (cmd_parms *cmd, void *dummy, const char *timeout, const char *steps) {
++    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
++    
++    if (err != NULL) {
++        return err;
++    }
++
++    processor_wait_timeout = atoi(timeout);
++
++    if (steps != NULL) {
++        int steps_tmp = atoi(steps);
++
++        if (steps_tmp < 1) {
++            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++                         "WARNING: Require ProcessorWaitTimeout steps > 0, setting to 1");
++            steps_tmp = 1;
++        }
++
++        processor_wait_steps = steps_tmp;
++    }
++
++    return NULL;
++}
++
 +static const command_rec peruser_cmds[] = {
 +UNIX_DAEMON_COMMANDS,
 +LISTEN_COMMANDS,
@@ -3472,24 +4205,38 @@ Index: httpd-2.2.6/server/mpm/experimental/peruser/peruser.c
 +              "Minimum number of idle children, to handle request spikes"),
 +AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
 +              "Minimum number of idle children, to handle request spikes"),
++AP_INIT_TAKE1("MaxSpareProcessors", set_max_free_processors, NULL, RSRC_CONF,
++              "Maximum number of idle children, 0 to disable"),
 +AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
 +              "Maximum number of children alive at the same time"),
 +AP_INIT_TAKE1("MinProcessors", set_min_processors, NULL, RSRC_CONF,
 +              "Minimum number of processors per vhost"),
 +AP_INIT_TAKE1("MaxProcessors", set_max_processors, NULL, RSRC_CONF,
 +              "Maximum number of processors per vhost"),
++AP_INIT_TAKE1("MinMultiplexers", set_min_multiplexers, NULL, RSRC_CONF,
++              "Minimum number of multiplexers the server can have"),
++AP_INIT_TAKE1("MaxMultiplexers", set_max_multiplexers, NULL, RSRC_CONF,
++              "Maximum number of multiplexers the server can have"),
 +AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
 +              "Maximum value of MaxClients for this run of Apache"),
 +AP_INIT_TAKE1("ExpireTimeout", set_expire_timeout, NULL, RSRC_CONF,
-+              "Maximum idle time before a child is killed, 0 to disable"),
++              "Maximum time a child can live, 0 to disable"),
 +AP_INIT_TAKE1("IdleTimeout", set_idle_timeout, NULL, RSRC_CONF,
 +              "Maximum time before a child is killed after being idle, 0 to disable"),
++AP_INIT_TAKE1("MultiplexerIdleTimeout", set_multiplexer_idle_timeout, NULL, RSRC_CONF,
++              "Maximum time before a multiplexer is killed after being idle, 0 to disable"),
++AP_INIT_TAKE12("ProcessorWaitTimeout", set_processor_wait_timeout, NULL, RSRC_CONF,
++              "Maximum time a multiplexer waits for the processor if it is busy"),
 +AP_INIT_TAKE23("Multiplexer", cf_Multiplexer, NULL, RSRC_CONF,
 +              "Specify an Multiplexer Child configuration."),
-+AP_INIT_TAKE23("Processor", cf_Processor, NULL, RSRC_CONF,
-+              "Specify a User and Group for a specific child process."),
-+AP_INIT_TAKE23("ServerEnvironment", cf_ServerEnvironment, NULL, RSRC_CONF,
++AP_INIT_RAW_ARGS("<Processor", cf_Processor, NULL, RSRC_CONF,
++              "Specify settings for processor."),
++AP_INIT_TAKE23("Processor", cf_Processor_depr, NULL, RSRC_CONF,
++              "A dummy directive for backwards compatibility"),
++AP_INIT_TAKE123("ServerEnvironment", cf_ServerEnvironment, NULL, RSRC_CONF,
 +              "Specify the server environment for this virtual host."),
++AP_INIT_TAKE1("MultiplexerChroot", cf_MultiplexerChroot, NULL, RSRC_CONF,
++              "Specify the multiplexer chroot path for multiplexer"),
 +{ NULL }
 +};
 +

diff --git a/2.2/patches/22_all_peruser_0.3.0-dc3.patch b/2.2/patches/22_all_peruser_0.3.0-dc3.patch
deleted file mode 100644
index 9bb7d17..0000000
--- a/2.2/patches/22_all_peruser_0.3.0-dc3.patch
+++ /dev/null
@@ -1,1211 +0,0 @@
---- httpd-2.2.3/server/mpm/experimental/peruser/mpm_default.h	2009-05-27 15:09:19.000000000 +0300
-+++ httpd-2.2.3-dc/server/mpm/experimental/peruser/mpm_default.h	2009-05-28 10:10:42.000000000 +0300
-@@ -77,6 +77,12 @@
- #define DEFAULT_MIN_FREE_PROCESSORS 2
- #endif
- 
-+/* Maximum --- more than this, and idle processors will be killed (0 = disable) */
-+
-+#ifndef DEFAULT_MAX_FREE_PROCESSORS
-+#define DEFAULT_MAX_FREE_PROCESSORS 0
-+#endif
-+
- /* Maximum processors per ServerEnvironment */
- 
- #ifndef DEFAULT_MAX_PROCESSORS
-@@ -107,4 +113,50 @@
- #define DEFAULT_MAX_REQUESTS_PER_CHILD 10000
- #endif
- 
-+/* Maximum multiplexers */
-+
-+#ifndef DEFAULT_MAX_MULTIPLEXERS
-+#define DEFAULT_MAX_MULTIPLEXERS 20
-+#endif
-+
-+/* Minimum multiplexers */
-+
-+#ifndef DEFAULT_MIN_MULTIPLEXERS
-+#define DEFAULT_MIN_MULTIPLEXERS 3
-+#endif
-+
-+/* Amount of time a child can run before it expires (0 = turn off) */
-+
-+#ifndef DEFAULT_EXPIRE_TIMEOUT
-+#define DEFAULT_EXPIRE_TIMEOUT 1800
-+#endif
-+
-+/* Amount of time a child can stay idle (0 = turn off) */
-+
-+#ifndef DEFAULT_IDLE_TIMEOUT
-+#define DEFAULT_IDLE_TIMEOUT 900
-+#endif
-+
-+/* Amount of time a multiplexer can stay idle (0 = turn off) */
-+
-+#ifndef DEFAULT_MULTIPLEXER_IDLE_TIMEOUT
-+#define DEFAULT_MULTIPLEXER_IDLE_TIMEOUT 0
-+#endif
-+
-+/* Amount of maximum time a multiplexer can wait for processor if it is busy (0 = never wait)
-+ * This is decreased with every busy request
-+ */
-+
-+#ifndef DEFAULT_PROCESSOR_WAIT_TIMEOUT
-+#define DEFAULT_PROCESSOR_WAIT_TIMEOUT 5
-+#endif
-+
-+/* The number of different levels there are when a multiplexer is waiting for processor
-+ * (between maximum waiting time and no waiting)
-+ */
-+
-+#ifndef DEFAULT_PROCESSOR_WAIT_STEPS
-+#define DEFAULT_PROCESSOR_WAIT_STEPS 10
-+#endif
-+
- #endif /* AP_MPM_DEFAULT_H */
---- httpd-2.2.3/server/mpm/experimental/peruser/mpm.h	2009-03-22 22:46:45.000000000 +0200
-+++ httpd-2.2.3-dc/server/mpm/experimental/peruser/mpm.h	2009-03-22 22:39:10.000000000 +0200
-@@ -84,6 +84,7 @@
- #define AP_MPM_USES_POD 1
- #define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
- #define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-+#define MPM_VALID_PID(p) (getpgid(p) == getpgrp())
- #define MPM_ACCEPT_FUNC unixd_accept
- 
- extern int ap_threads_per_child;
---- httpd-2.2.3/server/mpm/experimental/peruser/peruser.c	2009-05-27 15:09:19.000000000 +0300
-+++ httpd-2.2.3-dc/server/mpm/experimental/peruser/peruser.c	2009-05-28 13:54:27.000000000 +0300
-@@ -195,20 +195,30 @@
- 
- #define CHILD_STATUS_STANDBY  0  /* wait for a request before starting */
- #define CHILD_STATUS_STARTING 1  /* wait for socket creation */
--#define CHILD_STATUS_READY    2  /* wait for mux to restart */
--#define CHILD_STATUS_ACTIVE   3  /* ready to take requests */
-+#define CHILD_STATUS_READY    2  /* is ready to take requests */
-+#define CHILD_STATUS_ACTIVE   3  /* is currently busy handling requests */
- #define CHILD_STATUS_RESTART  4  /* child about to die and restart */
- 
-+/* cgroup settings */
-+#define CGROUP_TASKS_FILE "/tasks"
-+#define CGROUP_TASKS_FILE_LEN 7
-+
- /* config globals */
- 
- int ap_threads_per_child=0;         /* Worker threads per child */
- static apr_proc_mutex_t *accept_mutex;
- static int ap_min_processors=DEFAULT_MIN_PROCESSORS;
- static int ap_min_free_processors=DEFAULT_MIN_FREE_PROCESSORS;
-+static int ap_max_free_processors=DEFAULT_MAX_FREE_PROCESSORS;
- static int ap_max_processors=DEFAULT_MAX_PROCESSORS;
-+static int ap_min_multiplexers=DEFAULT_MIN_MULTIPLEXERS;
-+static int ap_max_multiplexers=DEFAULT_MAX_MULTIPLEXERS;
- static int ap_daemons_limit=0;      /* MaxClients */
--static int expire_timeout=1800;
--static int idle_timeout=900;
-+static int expire_timeout=DEFAULT_EXPIRE_TIMEOUT;
-+static int idle_timeout=DEFAULT_IDLE_TIMEOUT;
-+static int multiplexer_idle_timeout=DEFAULT_MULTIPLEXER_IDLE_TIMEOUT;
-+static int processor_wait_timeout=DEFAULT_PROCESSOR_WAIT_TIMEOUT;
-+static int processor_wait_steps=DEFAULT_PROCESSOR_WAIT_STEPS;
- static int server_limit = DEFAULT_SERVER_LIMIT;
- static int first_server_limit;
- static int changed_limit_at_restart;
-@@ -222,15 +232,21 @@
- {
-     int processor_id;
- 
-+    const char *name;	/* Server environment's unique string identifier */
-+
-     /* security settings */
-     uid_t uid;          /* user id */
-     gid_t gid;          /* group id */
-     const char *chroot; /* directory to chroot() to, can be null */
-+    int nice_lvl;
-+    const char *cgroup; /* cgroup directory, can be null */
- 
-     /* resource settings */
-     int min_processors;
-     int min_free_processors;
-+    int max_free_processors;
-     int max_processors;
-+    int availability;
- 
-     /* sockets */
-     int input;          /* The socket descriptor */
-@@ -437,6 +453,25 @@
-     return "UNKNOWN";
- }
- 
-+char* scoreboard_status_string(int status) {
-+    switch(status)
-+    {
-+        case SERVER_DEAD:  return "DEAD";
-+        case SERVER_STARTING: return "STARTING";
-+        case SERVER_READY:    return "READY";
-+        case SERVER_BUSY_READ:   return "BUSY_READ";
-+        case SERVER_BUSY_WRITE:   return "BUSY_WRITE";
-+        case SERVER_BUSY_KEEPALIVE:   return "BUSY_KEEPALIVE";
-+        case SERVER_BUSY_LOG:   return "BUSY_LOG";
-+        case SERVER_BUSY_DNS:   return "BUSY_DNS";
-+        case SERVER_CLOSING:   return "CLOSING";
-+        case SERVER_GRACEFUL:   return "GRACEFUL";
-+        case SERVER_NUM_STATUS:   return "NUM_STATUS";
-+    }
-+
-+    return "UNKNOWN";
-+}
-+
- void dump_child_table()
- {
- #ifdef MPM_PERUSER_DEBUG
-@@ -511,10 +546,6 @@
- 
- static void accept_mutex_on(void)
- {
--/* for some reason this fails if we listen on the pipe_of_death.
--   fortunately I don't think we currently need it */
--
--#if 0
-     apr_status_t rv = apr_proc_mutex_lock(accept_mutex);
-     if (rv != APR_SUCCESS) {
-         const char *msg = "couldn't grab the accept mutex";
-@@ -529,12 +560,10 @@
-             exit(APEXIT_CHILDFATAL);
-         }
-     }
--#endif
- }
- 
- static void accept_mutex_off(void)
- {
--#if 0
-     apr_status_t rv = apr_proc_mutex_unlock(accept_mutex);
-     if (rv != APR_SUCCESS) {
-         const char *msg = "couldn't release the accept mutex";
-@@ -552,7 +581,6 @@
-             exit(APEXIT_CHILDFATAL);
-         }
-     }
--#endif
- }
- 
- /* On some architectures it's safe to do unserialized accept()s in the single
-@@ -715,8 +743,10 @@
-     ret = apr_socket_recv(lr->sd, &pipe_read_char, &n);
-     if (APR_STATUS_IS_EAGAIN(ret))
-     {
--            /* It lost the lottery. It must continue to suffer
--             * through a life of servitude. */
-+       /* It lost the lottery. It must continue to suffer
-+        * through a life of servitude. */
-+       _DBG("POD read EAGAIN");
-+       return ret;
-     }
-     else
-     {
-@@ -1087,8 +1117,7 @@
-     for(i = 0, total = 0; i < NUM_CHILDS; ++i)
-     {
-         if(CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv &&
--           (SCOREBOARD_STATUS(i) == SERVER_STARTING ||
--            SCOREBOARD_STATUS(i) == SERVER_READY))
-+           (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY))
-         {
-             total++;
-         }
-@@ -1116,7 +1145,7 @@
-     apr_bucket *bucket;
-     const apr_array_header_t *headers_in_array;
-     const apr_table_entry_t *headers_in;
--    int counter;
-+    int counter, wait_time, wait_step_size;
- 
-     apr_socket_t *thesock = ap_get_module_config(r->connection->conn_config, &core_module);
- 
-@@ -1137,10 +1166,73 @@
-       apr_table_get(r->headers_in, "Host"), my_child_num, processor->senv->output);
-     _DBG("r->the_request=\"%s\" len=%d", r->the_request, strlen(r->the_request));
- 
--    ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len);
-+    wait_step_size = 100 / processor_wait_steps;
- 
--    /* Scan the brigade looking for heap-buckets */
-+    /*	Check if the processor is available */
-+    if (total_processors(processor->id) == processor->senv->max_processors &&
-+        idle_processors(processor->id) == 0) {
-+        /* The processor is currently busy, try to wait (a little) */
-+        _DBG("processor seems to be busy, trying to wait for it");
-+
-+        if (processor->senv->availability == 0) {
-+            processor->senv->availability = 0;
-+
-+            _DBG("processor is very busy (availability = 0) - not passing request");
-+
-+            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
-+                         "Too many requests for processor %s, increase MaxProcessors", processor->senv->name);
-+	    
-+            /* No point in waiting for the processor, it's very busy */
-+            return -1;
-+        }
-+        
-+        /* We sleep a little (depending how available the processor usually is) */
-+        int i;
-+        
-+        wait_time = (processor_wait_timeout / processor_wait_steps) * 1000000;
-+
-+        for(i = 0; i <= processor->senv->availability; i += wait_step_size) {
-+            usleep(wait_time);
- 
-+            /* Check if the processor is ready */
-+            if (total_processors(processor->id) < processor->senv->max_processors ||
-+                idle_processors(processor->id) > 0) {
-+                /* The processor has freed - lets use it */
-+                _DBG("processor freed before wait time expired");
-+                break;
-+            }
-+        }
-+        
-+        if (processor->senv->availability <= wait_step_size) {
-+            processor->senv->availability = 0;
-+        }
-+        else processor->senv->availability -= wait_step_size;
-+        
-+        /* Check if we waited all the time */
-+        if (i > processor->senv->availability) {
-+            _DBG("processor is busy - not passing request (availability = %d)",
-+                 processor->senv->availability);
-+            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf,
-+                         "Too many requests for processor %s, increase MaxProcessors", processor->senv->name);
-+            return -1;
-+        }
-+
-+        /* We could increase the availability a little here,
-+         * because the processor got freed eventually
-+         */
-+    }
-+    else {
-+        /* Smoothly increment the availability back to 100 */
-+        if (processor->senv->availability >= 100-wait_step_size) {
-+            processor->senv->availability = 100;
-+        }
-+        else processor->senv->availability += wait_step_size;
-+    }
-+    
-+    ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ, len);
-+    
-+    /* Scan the brigade looking for heap-buckets */
-+    
-     _DBG("Scanning the brigade",0);
-     bucket = APR_BRIGADE_FIRST(bb);
-     while (bucket != APR_BRIGADE_SENTINEL(bb) &&
-@@ -1294,12 +1386,22 @@
-     /* -- receive data from socket -- */
-     apr_os_sock_get(&ctrl_sock_fd, lr->sd);
-     _DBG("receiving from sock_fd=%d", ctrl_sock_fd);
--    ret = recvmsg(ctrl_sock_fd, &msg, 0);
- 
--    if(ret == -1)
--      _DBG("recvmsg failed with error \"%s\"", strerror(errno));
--    else
--      _DBG("recvmsg returned %d", ret);
-+    // Don't block
-+    ret = recvmsg(ctrl_sock_fd, &msg, MSG_DONTWAIT);
-+
-+    if (ret == -1 && errno == EAGAIN) {
-+        _DBG("receive_from_multiplexer recvmsg() EAGAIN, someone was faster");
-+        
-+        return APR_EAGAIN;
-+    }
-+    else if (ret == -1) {
-+        _DBG("recvmsg failed with error \"%s\"", strerror(errno));
-+        
-+        // Error, better kill this child to be on the safe side
-+        return APR_EGENERAL;
-+    }
-+    else _DBG("recvmsg returned %d", ret);
- 
-     /* -- extract socket from the cmsg -- */
-     memcpy(&trans_sock_fd, CMSG_DATA(cmsg), sizeof(trans_sock_fd));
-@@ -1399,10 +1501,58 @@
-     return 0;
- }
- 
--static int peruser_setup_child(int childnum)
-+static int peruser_setup_cgroup(int childnum, server_env_t *senv, apr_pool_t *pool)
-+{
-+    apr_file_t *file;
-+    int length;
-+    apr_size_t content_len;
-+    char *tasks_file, *content, *pos;
-+
-+    _DBG("starting to add pid to cgroup %s", senv->cgroup);
-+
-+    length = strlen(senv->cgroup) + CGROUP_TASKS_FILE_LEN;
-+    tasks_file = malloc(length);
-+
-+    if (!tasks_file) return -1;
-+
-+    pos = apr_cpystrn(tasks_file, senv->cgroup, length);
-+    apr_cpystrn(pos, CGROUP_TASKS_FILE, CGROUP_TASKS_FILE_LEN);
-+
-+    /* Prepare the data to be written to tasks file */
-+    content = apr_itoa(pool, ap_my_pid);
-+    content_len  = strlen(content);
-+
-+    _DBG("writing pid %s to tasks file %s", content, tasks_file);
-+
-+    if (apr_file_open(&file, tasks_file, APR_WRITE, APR_OS_DEFAULT, pool)) {
-+        ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
-+                     "cgroup: unable to open file %s",
-+                     tasks_file);
-+        free(tasks_file);
-+        return OK; /* don't fail if cgroup not available */
-+    }
-+
-+    if (apr_file_write(file, content, &content_len)) {
-+   	ap_log_error(APLOG_MARK, APLOG_ALERT, errno, NULL,
-+                     "cgroup: unable to write pid to file %s",
-+                     tasks_file);
-+    }
-+
-+    apr_file_close(file);
-+
-+    free(tasks_file);
-+
-+    return OK;
-+}
-+
-+static int peruser_setup_child(int childnum, apr_pool_t *pool)
- {
-     server_env_t *senv = CHILD_INFO_TABLE[childnum].senv;
- 
-+    if (senv->nice_lvl != 0) {
-+        nice(senv->nice_lvl);
-+    }
-+
-     if(senv->chroot) {
-       _DBG("chdir to %s", senv->chroot);
-       if(chdir(senv->chroot)) {
-@@ -1421,6 +1571,10 @@
-       }
-     }
- 
-+    if(senv->cgroup) {
-+   	peruser_setup_cgroup(childnum, senv, pool);
-+    }
-+
-     if (senv->uid == -1 && senv->gid == -1) {
-         return unixd_setup_child();
-     }
-@@ -1594,15 +1748,6 @@
-     {
-         case CHILD_TYPE_MULTIPLEXER:
-             _DBG("MULTIPLEXER %d", my_child_num);
--
--            /* update status on processors that are ready to accept requests */
--            _DBG("updating processor stati", 0);
--            for(i = 0; i < NUM_CHILDS; ++i)
--            {
--                if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY)
--                    CHILD_INFO_TABLE[i].status = CHILD_STATUS_ACTIVE;
--            }
--
-             break;
- 
-         case CHILD_TYPE_PROCESSOR:
-@@ -1626,7 +1771,7 @@
-     apr_os_sock_put(&pod_sock, &fd, pconf);
-     listen_add(pconf, pod_sock, check_pipe_of_death);
- 
--    if(peruser_setup_child(my_child_num) != 0)
-+    if(peruser_setup_child(my_child_num, pchild) != 0)
-         clean_child_exit(APEXIT_CHILDFATAL);
- 
-     ap_run_child_init(pchild, ap_server_conf);
-@@ -1670,14 +1815,19 @@
- 	    clean_child_exit(0);
- 	}
- 
--	(void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
-+        (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL);
-+
-+        CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_READY;
-+        _DBG("Child %d (%s) is now ready", my_child_num, child_type_string(CHILD_INFO_TABLE[my_child_num].type));
- 
- 	/*
- 	 * Wait for an acceptable connection to arrive.
- 	 */
- 
--	/* Lock around "accept", if necessary */
--	SAFE_ACCEPT(accept_mutex_on());
-+        /* Lock around "accept", if necessary */
-+        if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
-+            SAFE_ACCEPT(accept_mutex_on());
-+        }
- 
-         if (num_listensocks == 1) {
-             offset = 0;
-@@ -1729,18 +1879,27 @@
-          * defer the exit
-          */
-         status = listensocks[offset].accept_func((void *)&sock, &listensocks[offset], ptrans);
--        SAFE_ACCEPT(accept_mutex_off()); 	/* unlock after "accept" */
-+
-+        if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
-+            SAFE_ACCEPT(accept_mutex_off()); 	/* unlock after "accept" */
-+        }
- 
-         if (status == APR_EGENERAL) {
-             /* resource shortage or should-not-occur occured */
-             clean_child_exit(1);
-         }
--        else if (status != APR_SUCCESS || die_now) {
-+        else if (status != APR_SUCCESS || die_now || sock == NULL) {
-             continue;
-         }
- 
-+        if (CHILD_INFO_TABLE[my_child_num].status == CHILD_STATUS_READY) {
-+            CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_ACTIVE;
-+            _DBG("Child %d (%s) is now active", my_child_num, child_type_string(CHILD_INFO_TABLE[my_child_num].type));
-+        }
-+
-         if (CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_PROCESSOR ||
--            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER)
-+            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_WORKER ||
-+            CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER)
-         {
-           _DBG("CHECKING IF WE SHOULD CLONE A CHILD...");
- 
-@@ -1754,8 +1913,11 @@
- 
-           if(total_processors(my_child_num) <
-               CHILD_INFO_TABLE[my_child_num].senv->max_processors &&
--            idle_processors(my_child_num) <=
--              CHILD_INFO_TABLE[my_child_num].senv->min_free_processors)
-+            (idle_processors(my_child_num) <=
-+              CHILD_INFO_TABLE[my_child_num].senv->min_free_processors ||
-+             total_processors(my_child_num) <
-+              CHILD_INFO_TABLE[my_child_num].senv->min_processors
-+            ))
-           {
-               _DBG("CLONING CHILD");
-               child_clone();
-@@ -1804,46 +1966,80 @@
-     clean_child_exit(0);
- }
- 
--static server_env_t* senv_add(int uid, int gid, const char* chroot)
--{
-+static server_env_t* find_senv_by_name(const char *name) {
-     int i;
--    int socks[2];
- 
--    _DBG("Searching for matching senv...");
-+    if (name == NULL) return NULL;
-+
-+    _DBG("name=%s", name);
-+
-+    for(i = 0; i < NUM_SENV; i++)
-+      {
-+          if(SENV[i].name != NULL && !strcmp(SENV[i].name, name)) {
-+              return &SENV[i];
-+          }
-+      }
-+
-+    return NULL;
-+}
-+
-+static server_env_t* find_matching_senv(server_env_t* senv) {
-+    int i;
-+
-+    _DBG("name=%s uid=%d gid=%d chroot=%s", senv->name, senv->uid, senv->gid, senv->chroot);
- 
-     for(i = 0; i < NUM_SENV; i++)
--    {
--      if(SENV[i].uid == uid && SENV[i].gid == gid &&
--         (SENV[i].chroot == NULL || !strcmp(SENV[i].chroot, chroot)))
-       {
--          _DBG("Found existing senv: %i", i);
--          return &SENV[i];
-+          if((senv->name != NULL && SENV[i].name != NULL && !strcmp(SENV[i].name, senv->name)) ||
-+             (senv->name == NULL && SENV[i].uid == senv->uid && SENV[i].gid == senv->gid &&
-+              (
-+               (SENV[i].chroot == NULL && senv->chroot == NULL) ||
-+               ((SENV[i].chroot != NULL || senv->chroot != NULL) && !strcmp(SENV[i].chroot, senv->chroot)))
-+              )
-+             ) {
-+              return &SENV[i];
-+          }
-       }
-+
-+    return NULL;
-+}
-+
-+static server_env_t* senv_add(server_env_t *senv)
-+{
-+    int socks[2];
-+    server_env_t *old_senv;
-+
-+    _DBG("Searching for matching senv...");
-+
-+    old_senv = find_matching_senv(senv);
-+
-+    if (old_senv) {
-+        _DBG("Found existing senv");
-+        senv = old_senv;
-+        return old_senv;
-     }
- 
-     if(NUM_SENV >= server_limit)
--    {
--      _DBG("server_limit reached!");
--      return NULL;
--    }
-+      {
-+          _DBG("server_limit reached!");
-+          return NULL;
-+      }
- 
-     _DBG("Creating new senv");
- 
--    SENV[NUM_SENV].uid = uid;
--    SENV[NUM_SENV].gid = gid;
--    SENV[NUM_SENV].chroot = chroot;
--
--    SENV[NUM_SENV].min_processors = ap_min_processors;
--    SENV[NUM_SENV].min_free_processors = ap_min_free_processors;
--    SENV[NUM_SENV].max_processors = ap_max_processors;
-+    memcpy(&SENV[NUM_SENV], senv, sizeof(server_env_t));
-+
-+    SENV[NUM_SENV].availability = 100;
- 
-     socketpair(PF_UNIX, SOCK_STREAM, 0, socks);
-     SENV[NUM_SENV].input  = socks[0];
-     SENV[NUM_SENV].output = socks[1];
- 
-+    senv = &SENV[NUM_SENV];
-     return &SENV[server_env_image->control->num++];
- }
- 
-+
- static const char* child_clone()
- {
-     int i;
-@@ -1869,7 +2065,14 @@
-     new = &CHILD_INFO_TABLE[i];
- 
-     new->senv = this->senv;
--    new->type = CHILD_TYPE_WORKER;
-+
-+    if (this->type == CHILD_TYPE_MULTIPLEXER) {
-+        new->type = CHILD_TYPE_MULTIPLEXER;
-+    }
-+    else {
-+        new->type = CHILD_TYPE_WORKER;
-+    }
-+
-     new->sock_fd = this->sock_fd;
-     new->status = CHILD_STATUS_STARTING;
- 
-@@ -1878,7 +2081,7 @@
- }
- 
- static const char* child_add(int type, int status,
--                             apr_pool_t *pool, uid_t uid, gid_t gid, const char* chroot)
-+                             apr_pool_t *pool, server_env_t *senv)
- {
-     _DBG("adding child #%d", NUM_CHILDS);
- 
-@@ -1888,10 +2091,10 @@
-                "Increase NumServers in your config file.";
-     }
- 
--       if (chroot && !ap_is_directory(pool, chroot))
--               return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", chroot);
-+       if (senv->chroot && !ap_is_directory(pool, senv->chroot))
-+               return apr_psprintf(pool, "Error: chroot directory [%s] does not exist", senv->chroot);
- 
--    CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(uid, gid, chroot);
-+    CHILD_INFO_TABLE[NUM_CHILDS].senv = senv_add(senv);
- 
-     if(CHILD_INFO_TABLE[NUM_CHILDS].senv == NULL)
-     {
-@@ -1907,10 +2110,10 @@
-     CHILD_INFO_TABLE[NUM_CHILDS].status = status;
- 
-     _DBG("[%d] uid=%d gid=%d type=%d chroot=%s",
--         NUM_CHILDS, uid, gid, type,
--         chroot);
-+         NUM_CHILDS, senv->uid, senv->gid, type,
-+         senv->chroot);
- 
--    if (uid == 0 || gid == 0)
-+    if (senv->uid == 0 || senv->gid == 0)
-     {
-         _DBG("Assigning root user/group to a child.", 0);
-     }
-@@ -1957,7 +2160,7 @@
-     (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING,
-                                                (request_rec *) NULL);
- 
--    CHILD_INFO_TABLE[slot].status = CHILD_STATUS_ACTIVE;
-+    CHILD_INFO_TABLE[slot].status = CHILD_STATUS_READY;
- 
- 
- #ifdef _OSD_POSIX
-@@ -2062,19 +2265,31 @@
-         if(CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING)
-           make_child(ap_server_conf, i);
-       }
--      else if(((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR || 
--               CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)  &&
--               ap_scoreboard_image->parent[i].pid > 1) &&
--               (idle_processors (i) > 1 || total_processes (i) == 1) && (
--                   (expire_timeout > 0 &&  ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && 
--                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) ||
--                   (idle_timeout >   0 &&  ap_scoreboard_image->servers[i][0].status == SERVER_READY &&  
--                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout)))
-+      else if(
-+    	      (((CHILD_INFO_TABLE[i].type == CHILD_TYPE_PROCESSOR ||
-+                 CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)  &&
-+                ap_scoreboard_image->parent[i].pid > 1) &&
-+               (idle_processors (i) > CHILD_INFO_TABLE[i].senv->min_free_processors || CHILD_INFO_TABLE[i].senv->min_free_processors == 0) &&
-+               total_processes (i) > CHILD_INFO_TABLE[i].senv->min_processors && 
-+               (
-+                (expire_timeout > 0 &&  ap_scoreboard_image->servers[i][0].status != SERVER_DEAD && 
-+                 apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > expire_timeout) ||
-+                (idle_timeout >   0 &&  ap_scoreboard_image->servers[i][0].status == SERVER_READY &&  
-+                 apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > idle_timeout) ||
-+                (CHILD_INFO_TABLE[i].senv->max_free_processors > 0 && CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY &&
-+                 idle_processors(i) > CHILD_INFO_TABLE[i].senv->max_free_processors))
-+               )
-+              || (CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER &&
-+                  (multiplexer_idle_timeout > 0 && ap_scoreboard_image->servers[i][0].status == SERVER_READY &&
-+                   apr_time_sec(now - ap_scoreboard_image->servers[i][0].last_used) > multiplexer_idle_timeout) &&
-+                  total_processors(i) > CHILD_INFO_TABLE[i].senv->min_processors
-+                  )
-+            )
-       {
-         CHILD_INFO_TABLE[i].pid = 0;
-         CHILD_INFO_TABLE[i].status = CHILD_STATUS_STANDBY;
- 
--        if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER)
-+        if(CHILD_INFO_TABLE[i].type == CHILD_TYPE_WORKER || CHILD_INFO_TABLE[i].type == CHILD_TYPE_MULTIPLEXER)
-         {
-           /* completely free up this slot */
- 
-@@ -2173,7 +2388,6 @@
-         return 1;
-     }
- 
--#if 0
- #if APR_USE_SYSVSEM_SERIALIZE
-     if (ap_accept_lock_mech == APR_LOCK_DEFAULT || 
-         ap_accept_lock_mech == APR_LOCK_SYSVSEM) {
-@@ -2189,7 +2403,6 @@
-             return 1;
-         }
-     }
--#endif
- 
-     if (!is_graceful) {
-         if (ap_run_pre_mpm(s->process->pool, SB_SHARED) != OK) {
-@@ -2598,7 +2811,10 @@
-     ap_listen_pre_config();
-     ap_min_processors = DEFAULT_MIN_PROCESSORS;
-     ap_min_free_processors = DEFAULT_MIN_FREE_PROCESSORS;
-+    ap_max_free_processors = DEFAULT_MAX_FREE_PROCESSORS;
-     ap_max_processors = DEFAULT_MAX_PROCESSORS;
-+    ap_min_multiplexers = DEFAULT_MIN_MULTIPLEXERS;
-+    ap_max_multiplexers = DEFAULT_MAX_MULTIPLEXERS;
-     ap_daemons_limit = server_limit;
-     ap_pid_fname = DEFAULT_PIDLOG;
-     ap_lock_fname = DEFAULT_LOCKFILE;
-@@ -2608,6 +2824,13 @@
- 	ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
- #endif
- 
-+    expire_timeout = DEFAULT_EXPIRE_TIMEOUT;
-+    idle_timeout = DEFAULT_IDLE_TIMEOUT;
-+    multiplexer_idle_timeout = DEFAULT_MULTIPLEXER_IDLE_TIMEOUT;
-+    processor_wait_timeout = DEFAULT_PROCESSOR_WAIT_TIMEOUT;
-+    processor_wait_steps = DEFAULT_PROCESSOR_WAIT_STEPS;
-+
-+
-     apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
- 
-     /* we need to know ServerLimit and ThreadLimit before we start processing
-@@ -2709,11 +2932,13 @@
-         server_env_image->control = (server_env_control*)shmem;
-         shmem += sizeof(server_env_control*);
-         server_env_image->table = (server_env_t*)shmem;
-+    }
- 
-+    if(restart_num <= 2) {
-+        _DBG("Cleaning server environments table");
-+    
-         server_env_image->control->num = 0;
--
--        for (i = 0; i < tmp_server_limit; i++)
--        {
-+        for (i = 0; i < tmp_server_limit; i++) {
-             SENV[i].processor_id = -1;
-             SENV[i].uid          = -1;
-             SENV[i].gid          = -1;
-@@ -2781,8 +3006,8 @@
-                 if (pass_request(r, processor) == -1)
-                 {
-                     ap_log_error(APLOG_MARK, APLOG_ERR, 0,
--                             ap_server_conf, "Could not pass request to proper "                             "child, request will not be honoured.");
--                    return DECLINED;
-+                                 ap_server_conf, "Could not pass request to processor %s (virtualhost %s), request will not be honoured.",
-+                                 processor->senv->name, r->hostname);
-                 }
-                 _DBG("doing longjmp",0);
-                 longjmp(CHILD_INFO_TABLE[my_child_num].jmpbuffer, 1);
-@@ -2859,32 +3084,37 @@
-     ap_rputs("<hr>\n", r);
-     ap_rputs("<h2>peruser status</h2>\n", r);
-     ap_rputs("<table border=\"0\">\n", r);
--    ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>TYPE</td><td>UID</td>"
--                   "<td>GID</td><td>CHROOT</td><td>INPUT</td>"
-+    ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>SB STATUS</td><td>TYPE</td><td>UID</td>"
-+                   "<td>GID</td><td>CHROOT</td><td>NICE</td><td>INPUT</td>"
-                    "<td>OUTPUT</td><td>SOCK_FD</td>"
-                    "<td>TOTAL PROCESSORS</td><td>MAX PROCESSORS</td>"
--                   "<td>IDLE PROCESSORS</td><td>MIN FREE PROCESSORS</td></tr>\n", r);
-+                   "<td>IDLE PROCESSORS</td><td>MIN FREE PROCESSORS</td>"
-+                   "<td>AVAIL</td>"
-+                   "</tr>\n", r);
-     for (x = 0; x < NUM_CHILDS; x++)
-         {
-         senv = CHILD_INFO_TABLE[x].senv;
--        ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%12s</td>"
--                       "<td>%4d</td><td>%4d</td><td>%25s</td><td>%5d</td>"
-+        ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%8s</td><td>%12s</td>"
-+                       "<td>%4d</td><td>%4d</td><td>%25s</td><td>%3d</td><td>%5d</td>"
-                        "<td>%6d</td><td>%7d</td><td>%d</td><td>%d</td>"
--                       "<td>%d</td><td>%d</td></tr>\n", 
-+                       "<td>%d</td><td>%d</td><td>%3d</td></tr>\n",
-                        CHILD_INFO_TABLE[x].id, 
-                        CHILD_INFO_TABLE[x].pid, 
-                        child_status_string(CHILD_INFO_TABLE[x].status), 
-+                       scoreboard_status_string(SCOREBOARD_STATUS(x)),
-                        child_type_string(CHILD_INFO_TABLE[x].type), 
-                        senv == NULL ? -1 : senv->uid, 
-                        senv == NULL ? -1 : senv->gid, 
-                        senv == NULL ? NULL : senv->chroot, 
-+                       senv == NULL ? 0 : senv->nice_lvl,
-                        senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->input, 
-                        senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->output, 
-                        CHILD_INFO_TABLE[x].sock_fd,
-                        total_processors(x), 
-                        senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->max_processors,
-                        idle_processors(x),
--                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors
-+                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors,
-+                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->availability
-                        );
-        }
-     ap_rputs("</table>\n", r);
-@@ -2938,50 +3168,183 @@
-     APR_OPTIONAL_HOOK(ap, status_hook, peruser_status_hook, NULL, NULL, APR_HOOK_MIDDLE);
- }
- 
--/* we define an Processor w/ specific uid/gid */
--static const char *cf_Processor(cmd_parms *cmd, void *dummy,
--    const char *user_name, const char *group_name, const char *chroot)
-+static const char *cf_Processor(cmd_parms *cmd, void *dummy, const char *arg)
- {
--    uid_t uid = ap_uname2id(user_name);
--    gid_t gid = ap_gname2id(group_name);
-+    const char *user_name = NULL, *group_name = NULL, *directive;
-+    server_env_t senv;
-+    ap_directive_t *current;
-+
-+    const char *endp = ap_strrchr_c(arg, '>');
-+
-+    if (endp == NULL) {
-+	return apr_psprintf(cmd->temp_pool,
-+			    "Error: Directive %s> missing closing '>'", cmd->cmd->name);
-+    }
-+
-+    arg = apr_pstrndup(cmd->pool, arg, endp - arg);
-+
-+    if (!arg) {
-+   	return apr_psprintf(cmd->temp_pool,
-+                            "Error: %s> must specify a processor name", cmd->cmd->name);
-+    }
-+
-+    senv.name = ap_getword_conf(cmd->pool, &arg);
-+    _DBG("processor_name: %s", senv.name);
-+
-+    if (strlen(senv.name) == 0) {
-+        return apr_psprintf(cmd->temp_pool,
-+                            "Error: Directive %s> takes one argument", cmd->cmd->name);
-+    }
-+
-+    /*	Check for existing processors on first launch and between gracefuls */
-+    if (restart_num == 1 || is_graceful) {
-+        server_env_t *old_senv = find_senv_by_name(senv.name);
-+
-+        if (old_senv) {
-+            return apr_psprintf(cmd->temp_pool,
-+                                "Error: Processor %s already defined", senv.name);
-+        }
-+    }
-+
-+    senv.nice_lvl 		= 0;
-+    senv.chroot 		= NULL;
-+    senv.cgroup			= NULL;
-+    senv.min_processors 	= ap_min_processors;
-+    senv.min_free_processors 	= ap_min_free_processors;
-+    senv.max_free_processors    = ap_max_free_processors;
-+    senv.max_processors 	= ap_max_processors;
-+
-+    current = cmd->directive->first_child;
-+
-+    int proc_temp = 0;
-+    for(; current != NULL; current = current->next) {
-+        directive = current->directive;
-+        
-+        if (!strcasecmp(directive, "user")) {
-+            user_name = current->args;
-+        }
-+        else if (!strcasecmp(directive, "group")) {
-+   	    group_name = current->args;
-+        }
-+        else if (!strcasecmp(directive, "chroot")) {
-+            senv.chroot = ap_getword_conf(cmd->pool, &current->args);
-+        }
-+        else if (!strcasecmp(directive, "nicelevel")) {
-+    	    senv.nice_lvl = atoi(current->args);
-+        }
-+        else if (!strcasecmp(directive, "maxprocessors")) {
-+            proc_temp = atoi(current->args);
-+
-+            if (proc_temp < 1) {
-+                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                             "WARNING: Require MaxProcessors > 0, setting to 1");
-+                proc_temp = 1;
-+            }
-+
-+            senv.max_processors = proc_temp;
-+        }
-+        else if (!strcasecmp(directive, "minprocessors")) {
-+            proc_temp = atoi(current->args);
-+
-+            if (proc_temp < 0) {
-+                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                             "WARNING: Require MinProcessors >= 0, setting to 0");
-+                proc_temp = 0;
-+            }
-+
-+            senv.min_processors = proc_temp;
-+        }
-+        else if (!strcasecmp(directive, "minspareprocessors")) {
-+            proc_temp = atoi(current->args);
- 
--    _DBG("user=%s:%d group=%s:%d chroot=%s",
--        user_name, uid, group_name, gid, chroot);
-+            if (proc_temp < 0) {
-+                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                             "WARNING: Require MinSpareProcessors >= 0, setting to 0");
-+                proc_temp = 0;
-+            }
-+
-+            senv.min_free_processors = proc_temp;
-+        }
-+        else if (!strcasecmp(directive, "maxspareprocessors")) {
-+            proc_temp = atoi(current->args);
-+            
-+            if (proc_temp < 0) {
-+                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                             "WARNING: Require MaxSpareProcessors >= 0, setting to 0");
-+                proc_temp = 0;
-+            }
-+
-+            senv.max_free_processors = proc_temp;
-+        }
-+        else if (!strcasecmp(directive, "cgroup")) {
-+            senv.cgroup = ap_getword_conf(cmd->pool, &current->args);
-+        }
-+        else {
-+            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                         "Unknown directive %s in %s>", directive, cmd->cmd->name);
-+        }
-+    }
-+
-+    if (user_name == NULL || group_name == NULL) {
-+        return apr_psprintf(cmd->temp_pool,
-+                            "Error: User or Group must be set in %s>", cmd->cmd->name);
-+    }
-+
-+    senv.uid = ap_uname2id(user_name);
-+    senv.gid = ap_gname2id(group_name);
-+
-+    _DBG("name=%s user=%s:%d group=%s:%d chroot=%s nice_lvl=%d",
-+         senv.name, user_name, senv.uid, group_name, senv.gid, senv.chroot, senv.nice_lvl);
-+
-+    _DBG("min_processors=%d min_free_processors=%d max_spare_processors=%d max_processors=%d",
-+         senv.min_processors, senv.min_free_processors, senv.max_free_processors, senv.max_processors);
- 
-     return child_add(CHILD_TYPE_PROCESSOR, CHILD_STATUS_STANDBY,
--                     cmd->pool, uid, gid, chroot);
-+                     cmd->pool, &senv);
- }
- 
- /* we define an Multiplexer child w/ specific uid/gid */
- static const char *cf_Multiplexer(cmd_parms *cmd, void *dummy,
-     const char *user_name, const char *group_name, const char *chroot)
- {
--    uid_t uid = ap_uname2id(user_name);
--    gid_t gid = ap_gname2id(group_name);
-+    server_env_t senv;
-+
-+    senv.name 		= NULL;
-+
-+    senv.uid 		= ap_uname2id(user_name);
-+    senv.gid 		= ap_gname2id(group_name);
-+    senv.nice_lvl 	= 0;
-+    senv.cgroup		= NULL;
-+    senv.chroot         = chroot;
-+
-+    senv.min_processors 	= ap_min_multiplexers;
-+    senv.min_free_processors 	= ap_min_free_processors;
-+    senv.max_free_processors    = ap_max_free_processors;
-+    senv.max_processors 	= ap_max_multiplexers;
- 
-     _DBG("user=%s:%d group=%s:%d chroot=%s [multiplexer id %d]",
--        user_name, uid, group_name, gid, chroot, NUM_CHILDS);
-+        user_name, senv.uid, group_name, senv.gid, senv.chroot, NUM_CHILDS);
- 
-     return child_add(CHILD_TYPE_MULTIPLEXER, CHILD_STATUS_STARTING,
--                     cmd->pool, uid, gid, chroot);
-+                     cmd->pool, &senv);
- }
- 
- static const char* cf_ServerEnvironment(cmd_parms *cmd, void *dummy,
--    const char *user_name, const char *group_name, const char *chroot)
-+    const char *name)
- {
--    int uid = ap_uname2id(user_name);
--    int gid = ap_gname2id(group_name);
-     peruser_server_conf *sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
- 
-     _DBG("function entered", 0);
- 
--       if (chroot && !ap_is_directory(cmd->pool, chroot))
--               return apr_psprintf(cmd->pool, "Error: chroot directory [%s] does not exist", chroot);
-+    sconf->senv = find_senv_by_name(name);
- 
--    sconf->senv = senv_add(uid, gid, chroot);
-+    if (sconf->senv == NULL) {
-+        return apr_psprintf(cmd->pool,
-+                            "Error: Processor %s not defined", name);
-+    }
- 
--    _DBG("user=%s:%d group=%s:%d chroot=%s numchilds=%d",
--        user_name, uid, group_name, gid, chroot, NUM_CHILDS);
-+    _DBG("user=%d group=%d chroot=%s numchilds=%d",
-+        sconf->senv->uid, sconf->senv->gid, sconf->senv->chroot, NUM_CHILDS);
- 
-     return NULL;
- }
-@@ -3046,10 +3409,10 @@
- 
-     min_procs = atoi(arg);
- 
--    if (min_procs < 1) {
-+    if (min_procs < 0) {
-         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
--                     "WARNING: Require MaxProcessors > 0, setting to 1");
--        min_procs = 1;
-+                     "WARNING: Require MinProcessors >= 0, setting to 0");
-+        min_procs = 0;
-     }
- 
-     if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
-@@ -3075,10 +3438,10 @@
- 
-     min_free_procs = atoi(arg);
- 
--    if (min_free_procs < 1) {
-+    if (min_free_procs < 0) {
-         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
--                     "WARNING: Require MinSpareProcessors > 0, setting to 1");
--        min_free_procs = 1;
-+                     "WARNING: Require MinSpareProcessors >= 0, setting to 0");
-+        min_free_procs = 0;
-     }
- 
-     if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
-@@ -3092,6 +3455,35 @@
-     return NULL;
- }
- 
-+static const char *set_max_free_processors (cmd_parms *cmd, void *dummy, const char *arg)
-+{
-+     peruser_server_conf *sconf;
-+     int max_free_procs;
-+     const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
-+
-+     if (err != NULL) {
-+         return err;
-+     }
-+
-+     max_free_procs = atoi(arg);
-+
-+     if (max_free_procs < 0) {
-+         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                      "WARNING: Require MaxSpareProcessors >= 0, setting to 0");
-+         max_free_procs = 0;
-+     }
-+
-+     if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
-+         sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
-+         sconf->senv->max_free_processors = max_free_procs;
-+     }
-+     else {
-+         ap_max_free_processors = max_free_procs;
-+     }
-+
-+     return NULL;
-+}
-+
- static const char *set_max_processors (cmd_parms *cmd, void *dummy, const char *arg)
- {
-     peruser_server_conf *sconf;
-@@ -3121,6 +3513,50 @@
-     return NULL;
- }
- 
-+static const char *set_min_multiplexers (cmd_parms *cmd, void *dummy, const char *arg)
-+{
-+    int min_multiplexers;
-+    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
-+
-+    if (err != NULL) {
-+        return err;
-+    }
-+
-+    min_multiplexers = atoi(arg);
-+
-+    if (min_multiplexers < 1) {
-+        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                     "WARNING: Require MinMultiplexers > 0, setting to 1");
-+        min_multiplexers = 1;
-+    }
-+
-+    ap_min_multiplexers = min_multiplexers;
-+
-+    return NULL;
-+}
-+
-+static const char *set_max_multiplexers (cmd_parms *cmd, void *dummy, const char *arg)
-+{
-+    int max_multiplexers;
-+    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
-+
-+    if (err != NULL) {
-+        return err;
-+    }
-+
-+    max_multiplexers = atoi(arg);
-+
-+    if (max_multiplexers < 1) {
-+        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                     "WARNING: Require MaxMultiplexers > 0, setting to 1");
-+        max_multiplexers = 1;
-+    }
-+
-+    ap_max_multiplexers = max_multiplexers;
-+
-+    return NULL;
-+}
-+
- static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) 
- {
-     int tmp_server_limit;
-@@ -3183,6 +3619,42 @@
-     return NULL;
- }
- 
-+static const char *set_multiplexer_idle_timeout (cmd_parms *cmd, void *dummy, const char *arg) {
-+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
-+
-+    if (err != NULL) {
-+        return err;
-+    }
-+
-+    multiplexer_idle_timeout = atoi(arg);
-+
-+    return NULL;
-+}
-+
-+static const char *set_processor_wait_timeout (cmd_parms *cmd, void *dummy, const char *timeout, const char *steps) {
-+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
-+    
-+    if (err != NULL) {
-+        return err;
-+    }
-+
-+    processor_wait_timeout = atoi(timeout);
-+
-+    if (steps != NULL) {
-+        int steps_tmp = atoi(steps);
-+
-+        if (steps_tmp < 1) {
-+            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
-+                         "WARNING: Require ProcessorWaitTimeout steps > 0, setting to 1");
-+            steps_tmp = 1;
-+        }
-+
-+        processor_wait_steps = steps_tmp;
-+    }
-+
-+    return NULL;
-+}
-+
- static const command_rec peruser_cmds[] = {
- UNIX_DAEMON_COMMANDS,
- LISTEN_COMMANDS,
-@@ -3190,23 +3662,33 @@
-               "Minimum number of idle children, to handle request spikes"),
- AP_INIT_TAKE1("MinSpareServers", set_min_free_servers, NULL, RSRC_CONF,
-               "Minimum number of idle children, to handle request spikes"),
-+AP_INIT_TAKE1("MaxSpareProcessors", set_max_free_processors, NULL, RSRC_CONF,
-+              "Maximum number of idle children, 0 to disable"),
- AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
-               "Maximum number of children alive at the same time"),
- AP_INIT_TAKE1("MinProcessors", set_min_processors, NULL, RSRC_CONF,
-               "Minimum number of processors per vhost"),
- AP_INIT_TAKE1("MaxProcessors", set_max_processors, NULL, RSRC_CONF,
-               "Maximum number of processors per vhost"),
-+AP_INIT_TAKE1("MinMultiplexers", set_min_multiplexers, NULL, RSRC_CONF,
-+              "Minimum number of multiplexers the server can have"),
-+AP_INIT_TAKE1("MaxMultiplexers", set_max_multiplexers, NULL, RSRC_CONF,
-+              "Maximum number of multiplexers the server can have"),
- AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
-               "Maximum value of MaxClients for this run of Apache"),
- AP_INIT_TAKE1("ExpireTimeout", set_expire_timeout, NULL, RSRC_CONF,
--              "Maximum idle time before a child is killed, 0 to disable"),
-+              "Maximum time a child can live, 0 to disable"),
- AP_INIT_TAKE1("IdleTimeout", set_idle_timeout, NULL, RSRC_CONF,
-               "Maximum time before a child is killed after being idle, 0 to disable"),
-+AP_INIT_TAKE1("MultiplexerIdleTimeout", set_multiplexer_idle_timeout, NULL, RSRC_CONF,
-+              "Maximum time before a multiplexer is killed after being idle, 0 to disable"),
-+AP_INIT_TAKE12("ProcessorWaitTimeout", set_processor_wait_timeout, NULL, RSRC_CONF,
-+              "Maximum time a multiplexer waits for the processor if it is busy"),
- AP_INIT_TAKE23("Multiplexer", cf_Multiplexer, NULL, RSRC_CONF,
-               "Specify an Multiplexer Child configuration."),
--AP_INIT_TAKE23("Processor", cf_Processor, NULL, RSRC_CONF,
--              "Specify a User and Group for a specific child process."),
--AP_INIT_TAKE23("ServerEnvironment", cf_ServerEnvironment, NULL, RSRC_CONF,
-+AP_INIT_RAW_ARGS("<Processor", cf_Processor, NULL, RSRC_CONF,
-+              "Specify settings for processor."),
-+AP_INIT_TAKE1("ServerEnvironment", cf_ServerEnvironment, NULL, RSRC_CONF,
-               "Specify the server environment for this virtual host."),
- { NULL }
- };


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:33 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:33 UTC (permalink / raw
  To: gentoo-commits

commit:     68a2fd7aef2840ae86779dbb2ce55c0384e1c8ea
Author:     Benedikt Boehm <hollow <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  1 05:49:03 2010 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Wed Sep  1 05:49:03 2010 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=68a2fd7a

dump peruser to 0.4.0-rc1 wrt #294098

---
 ....4.0b1.patch => 20_all_peruser_0.4.0-rc1.patch} | 540 ++++++++++++++-------
 1 file changed, 367 insertions(+), 173 deletions(-)

diff --git a/2.2/patches/20_all_peruser_0.4.0b1.patch b/2.2/patches/20_all_peruser_0.4.0-rc1.patch
similarity index 92%
rename from 2.2/patches/20_all_peruser_0.4.0b1.patch
rename to 2.2/patches/20_all_peruser_0.4.0-rc1.patch
index 8e30e64..782bab5 100644
--- a/2.2/patches/20_all_peruser_0.4.0b1.patch
+++ b/2.2/patches/20_all_peruser_0.4.0-rc1.patch
@@ -1,6 +1,102 @@
-diff -Nur httpd-2.2.13/modules/ssl/mod_ssl.h httpd-2.2.13-peruser/modules/ssl/mod_ssl.h
---- httpd-2.2.13/modules/ssl/mod_ssl.h	2006-07-12 06:38:44.000000000 +0300
-+++ httpd-2.2.13-peruser/modules/ssl/mod_ssl.h	2009-09-01 16:19:22.000000000 +0300
+diff -ruN httpd-2.2.14/docs/conf/extra/httpd-mpm.conf.in peruser-0.4rc1/docs/conf/extra/httpd-mpm.conf.in
+--- httpd-2.2.14/docs/conf/extra/httpd-mpm.conf.in	2007-12-29 04:08:28.000000000 +0100
++++ peruser-0.4rc1/docs/conf/extra/httpd-mpm.conf.in	2009-11-21 21:38:45.000000000 +0100
+@@ -27,6 +27,24 @@
+ # active mpm.
+ #
+ 
++# peruser MPM
++# IdleTimeout: maximum time before a child is killed after being idle, 0 to disable
++# ExpireTimeout: maximum time a child can live, 0 to disable
++# MinSpareProcessors: minimum number of idle children, to handle request spikes
++# MaxProcessors: Maximum number of processors per vhost
++# ServerLimit: maximum value of MaxClients for this run of Apache
++# MaxClients: maximum number of children alive at the same time
++# MaxMultiplexers: maximum number of multiplexers the server can have
++<IfModule mpm_peruser_module>
++    IdleTimeout 900
++    ExpireTimeout 1800
++    MinSpareProcessors 2
++    MaxProcessors 10
++    ServerLimit 256
++    MaxClients 256
++    MaxMultiplexers 20
++</IfModule>
++
+ # prefork MPM
+ # StartServers: number of server processes to start
+ # MinSpareServers: minimum number of server processes which are kept spare
+diff -ruN httpd-2.2.14/modules/generators/mod_status.c peruser-0.4rc1/modules/generators/mod_status.c
+--- httpd-2.2.14/modules/generators/mod_status.c	2008-01-02 10:43:52.000000000 +0100
++++ peruser-0.4rc1/modules/generators/mod_status.c	2009-11-21 21:07:28.000000000 +0100
+@@ -205,6 +205,7 @@
+ #define STAT_OPT_REFRESH  0
+ #define STAT_OPT_NOTABLE  1
+ #define STAT_OPT_AUTO     2
++#define STAT_OPT_STATS    3
+ 
+ struct stat_opt {
+     int id;
+@@ -217,6 +218,7 @@
+     {STAT_OPT_REFRESH, "refresh", "Refresh"},
+     {STAT_OPT_NOTABLE, "notable", NULL},
+     {STAT_OPT_AUTO, "auto", NULL},
++    {STAT_OPT_STATS, "stats", NULL},
+     {STAT_OPT_END, NULL, NULL}
+ };
+ 
+@@ -241,6 +243,7 @@
+ #endif
+     int short_report;
+     int no_table_report;
++	int stats_report;
+     worker_score *ws_record;
+     process_score *ps_record;
+     char *stat_buffer;
+@@ -268,7 +271,8 @@
+     kbcount = 0;
+     short_report = 0;
+     no_table_report = 0;
+-
++	stats_report=0;
++	
+     pid_buffer = apr_palloc(r->pool, server_limit * sizeof(pid_t));
+     stat_buffer = apr_palloc(r->pool, server_limit * thread_limit * sizeof(char));
+ 
+@@ -312,6 +316,9 @@
+                 case STAT_OPT_NOTABLE:
+                     no_table_report = 1;
+                     break;
++               case STAT_OPT_STATS:
++                    stats_report = 1;
++                    break;
+                 case STAT_OPT_AUTO:
+                     ap_set_content_type(r, "text/plain; charset=ISO-8859-1");
+                     short_report = 1;
+@@ -819,7 +826,8 @@
+         int flags =
+             (short_report ? AP_STATUS_SHORT : 0) |
+             (no_table_report ? AP_STATUS_NOTABLE : 0) |
+-            (ap_extended_status ? AP_STATUS_EXTENDED : 0);
++            (ap_extended_status ? AP_STATUS_EXTENDED : 0) |
++            (stats_report ? AP_STATUS_STATS : 0);
+ 
+         ap_run_status_hook(r, flags);
+     }
+diff -ruN httpd-2.2.14/modules/generators/mod_status.h peruser-0.4rc1/modules/generators/mod_status.h
+--- httpd-2.2.14/modules/generators/mod_status.h	2006-07-12 05:38:44.000000000 +0200
++++ peruser-0.4rc1/modules/generators/mod_status.h	2009-11-21 21:07:28.000000000 +0100
+@@ -32,6 +32,7 @@
+ #define AP_STATUS_SHORT    (0x1)  /* short, non-HTML report requested */
+ #define AP_STATUS_NOTABLE  (0x2)  /* HTML report without tables */
+ #define AP_STATUS_EXTENDED (0x4)  /* detailed report */
++#define AP_STATUS_STATS    (0x8)  /* extended user statistics report */
+ 
+ #if !defined(WIN32)
+ #define STATUS_DECLARE(type)            type
+diff -ruN httpd-2.2.14/modules/ssl/mod_ssl.h peruser-0.4rc1/modules/ssl/mod_ssl.h
+--- httpd-2.2.14/modules/ssl/mod_ssl.h	2006-07-12 05:38:44.000000000 +0200
++++ peruser-0.4rc1/modules/ssl/mod_ssl.h	2009-11-21 14:29:17.000000000 +0100
 @@ -50,6 +50,10 @@
   * is using SSL/TLS. */
  APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
@@ -12,9 +108,9 @@ diff -Nur httpd-2.2.13/modules/ssl/mod_ssl.h httpd-2.2.13-peruser/modules/ssl/mo
  /** The ssl_proxy_enable() and ssl_engine_disable() optional functions
   * are used by mod_proxy to enable use of SSL for outgoing
   * connections. */
-diff -Nur httpd-2.2.13/modules/ssl/ssl_engine_vars.c httpd-2.2.13-peruser/modules/ssl/ssl_engine_vars.c
---- httpd-2.2.13/modules/ssl/ssl_engine_vars.c	2009-08-06 10:28:47.000000000 +0300
-+++ httpd-2.2.13-peruser/modules/ssl/ssl_engine_vars.c	2009-09-01 16:19:22.000000000 +0300
+diff -ruN httpd-2.2.14/modules/ssl/ssl_engine_vars.c peruser-0.4rc1/modules/ssl/ssl_engine_vars.c
+--- httpd-2.2.14/modules/ssl/ssl_engine_vars.c	2009-09-06 13:19:05.000000000 +0200
++++ peruser-0.4rc1/modules/ssl/ssl_engine_vars.c	2009-11-21 14:33:56.000000000 +0100
 @@ -58,6 +58,12 @@
      return sslconn && sslconn->ssl;
  }
@@ -36,9 +132,9 @@ diff -Nur httpd-2.2.13/modules/ssl/ssl_engine_vars.c httpd-2.2.13-peruser/module
      APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
      APR_REGISTER_OPTIONAL_FN(ssl_ext_lookup);
  
-diff -Nur httpd-2.2.13/server/mpm/config.m4 httpd-2.2.13-peruser/server/mpm/config.m4
---- httpd-2.2.13/server/mpm/config.m4	2005-10-30 19:05:26.000000000 +0200
-+++ httpd-2.2.13-peruser/server/mpm/config.m4	2009-09-01 16:19:22.000000000 +0300
+diff -ruN httpd-2.2.14/server/mpm/config.m4 peruser-0.4rc1/server/mpm/config.m4
+--- httpd-2.2.14/server/mpm/config.m4	2005-10-30 18:05:26.000000000 +0100
++++ peruser-0.4rc1/server/mpm/config.m4	2009-11-21 14:29:17.000000000 +0100
 @@ -1,7 +1,7 @@
  AC_MSG_CHECKING(which MPM to use)
  AC_ARG_WITH(mpm,
@@ -57,9 +153,9 @@ diff -Nur httpd-2.2.13/server/mpm/config.m4 httpd-2.2.13-peruser/server/mpm/conf
          return 0
      else
          return 1
-diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/AUTHORS httpd-2.2.13-peruser/server/mpm/experimental/peruser/AUTHORS
---- httpd-2.2.13/server/mpm/experimental/peruser/AUTHORS	1970-01-01 03:00:00.000000000 +0300
-+++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/AUTHORS	2009-09-01 16:19:22.000000000 +0300
+diff -ruN httpd-2.2.14/server/mpm/experimental/peruser/AUTHORS peruser-0.4rc1/server/mpm/experimental/peruser/AUTHORS
+--- httpd-2.2.14/server/mpm/experimental/peruser/AUTHORS	1970-01-01 01:00:00.000000000 +0100
++++ peruser-0.4rc1/server/mpm/experimental/peruser/AUTHORS	2009-11-21 14:29:17.000000000 +0100
 @@ -0,0 +1,11 @@
 +Enrico Weigelt <weigelt [at] metux.de> (MetuxMPM maintainer)
 +Sean Gabriel Heacock <gabriel [at] telana.com> (Peruser maintainer)
@@ -72,25 +168,136 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/AUTHORS httpd-2.2.13-peru
 +Steve Amerige <mpm [at] fatbear.com>
 +Stefan Klingner <stefan.klingner [at] mephisto23.com> (Peruser maintainer)
 +Michal Grzedzicki <lazy404 [at] gmail.com>
-diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/config.m4 httpd-2.2.13-peruser/server/mpm/experimental/peruser/config.m4
---- httpd-2.2.13/server/mpm/experimental/peruser/config.m4	1970-01-01 03:00:00.000000000 +0300
-+++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/config.m4	2009-09-01 16:19:22.000000000 +0300
-@@ -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.13/server/mpm/experimental/peruser/Makefile.in httpd-2.2.13-peruser/server/mpm/experimental/peruser/Makefile.in
---- httpd-2.2.13/server/mpm/experimental/peruser/Makefile.in	1970-01-01 03:00:00.000000000 +0300
-+++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/Makefile.in	2009-09-01 16:19:22.000000000 +0300
+diff -ruN httpd-2.2.14/server/mpm/experimental/peruser/Makefile.in peruser-0.4rc1/server/mpm/experimental/peruser/Makefile.in
+--- httpd-2.2.14/server/mpm/experimental/peruser/Makefile.in	1970-01-01 01:00:00.000000000 +0100
++++ peruser-0.4rc1/server/mpm/experimental/peruser/Makefile.in	2009-11-21 14:29:17.000000000 +0100
 @@ -0,0 +1,5 @@
 +
 +LTLIBRARY_NAME    = libperuser.la
 +LTLIBRARY_SOURCES = peruser.c
 +
 +include $(top_srcdir)/build/ltlib.mk
-diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/mpm_default.h httpd-2.2.13-peruser/server/mpm/experimental/peruser/mpm_default.h
---- httpd-2.2.13/server/mpm/experimental/peruser/mpm_default.h	1970-01-01 03:00:00.000000000 +0300
-+++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/mpm_default.h	2009-09-01 16:19:22.000000000 +0300
+diff -ruN httpd-2.2.14/server/mpm/experimental/peruser/config.m4 peruser-0.4rc1/server/mpm/experimental/peruser/config.m4
+--- httpd-2.2.14/server/mpm/experimental/peruser/config.m4	1970-01-01 01:00:00.000000000 +0100
++++ peruser-0.4rc1/server/mpm/experimental/peruser/config.m4	2009-11-21 14:29:17.000000000 +0100
+@@ -0,0 +1,3 @@
++if test "$MPM_NAME" = "peruser" ; then
++    APACHE_FAST_OUTPUT(server/mpm/experimental/$MPM_NAME/Makefile)
++fi
+diff -ruN httpd-2.2.14/server/mpm/experimental/peruser/mpm.h peruser-0.4rc1/server/mpm/experimental/peruser/mpm.h
+--- httpd-2.2.14/server/mpm/experimental/peruser/mpm.h	1970-01-01 01:00:00.000000000 +0100
++++ peruser-0.4rc1/server/mpm/experimental/peruser/mpm.h	2009-11-21 21:10:39.000000000 +0100
+@@ -0,0 +1,107 @@
++/* ====================================================================
++ * The Apache Software License, Version 1.1
++ *
++ * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
++ * reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in
++ *    the documentation and/or other materials provided with the
++ *    distribution.
++ *
++ * 3. The end-user documentation included with the redistribution,
++ *    if any, must include the following acknowledgment:
++ *       "This product includes software developed by the
++ *        Apache Software Foundation (http://www.apache.org/)."
++ *    Alternately, this acknowledgment may appear in the software itself,
++ *    if and wherever such third-party acknowledgments normally appear.
++ *
++ * 4. The names "Apache" and "Apache Software Foundation" must
++ *    not be used to endorse or promote products derived from this
++ *    software without prior written permission. For written
++ *    permission, please contact apache@apache.org.
++ *
++ * 5. Products derived from this software may not be called "Apache",
++ *    nor may "Apache" appear in their name, without prior written
++ *    permission of the Apache Software Foundation.
++ *
++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This software consists of voluntary contributions made by many
++ * individuals on behalf of the Apache Software Foundation.  For more
++ * information on the Apache Software Foundation, please see
++ * <http://www.apache.org/>.
++ *
++ * Portions of this software are based upon public domain software
++ * originally written at the National Center for Supercomputing Applications,
++ * University of Illinois, Urbana-Champaign.
++ */
++
++#include "httpd.h"
++#include "mpm_default.h"
++#include "scoreboard.h"
++#include "unixd.h"
++
++#ifndef APACHE_MPM_PERUSER_H
++#define APACHE_MPM_PERUSER_H
++
++#define PERUSER_MPM
++
++#define MPM_NAME "Peruser"
++
++#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
++#define AP_MPM_WANT_WAIT_OR_TIMEOUT
++#define AP_MPM_WANT_PROCESS_CHILD_STATUS
++#define AP_MPM_WANT_SET_PIDFILE
++#define AP_MPM_WANT_SET_SCOREBOARD
++#define AP_MPM_WANT_SET_LOCKFILE
++#define AP_MPM_WANT_SET_MAX_REQUESTS
++#define AP_MPM_WANT_SET_COREDUMPDIR
++#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
++#define AP_MPM_WANT_SIGNAL_SERVER
++#define AP_MPM_WANT_SET_MAX_MEM_FREE
++#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
++
++#define AP_MPM_USES_POD 1
++#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
++#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
++#define MPM_VALID_PID(p) (getpgid(p) == getpgrp())
++#define MPM_ACCEPT_FUNC unixd_accept
++
++extern int ap_threads_per_child;
++extern int ap_max_daemons_limit;
++extern server_rec *ap_server_conf;
++
++/* Table of child status */
++#define SERVER_DEAD 0
++#define SERVER_DYING 1
++#define SERVER_ALIVE 2
++
++typedef struct ap_ctable {
++    pid_t pid;
++    unsigned char status;
++} ap_ctable;
++
++static const char* child_clone();
++
++
++#endif /* APACHE_MPM_PERUSER_H */
+diff -ruN httpd-2.2.14/server/mpm/experimental/peruser/mpm_default.h peruser-0.4rc1/server/mpm/experimental/peruser/mpm_default.h
+--- httpd-2.2.14/server/mpm/experimental/peruser/mpm_default.h	1970-01-01 01:00:00.000000000 +0100
++++ peruser-0.4rc1/server/mpm/experimental/peruser/mpm_default.h	2009-11-21 14:29:17.000000000 +0100
 @@ -0,0 +1,162 @@
 +/* ====================================================================
 + * The Apache Software License, Version 1.1
@@ -254,118 +461,10 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/mpm_default.h httpd-2.2.1
 +#endif
 +
 +#endif /* AP_MPM_DEFAULT_H */
-diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/mpm.h httpd-2.2.13-peruser/server/mpm/experimental/peruser/mpm.h
---- httpd-2.2.13/server/mpm/experimental/peruser/mpm.h	1970-01-01 03:00:00.000000000 +0300
-+++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/mpm.h	2009-09-01 16:19:22.000000000 +0300
-@@ -0,0 +1,104 @@
-+/* ====================================================================
-+ * The Apache Software License, Version 1.1
-+ *
-+ * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
-+ * reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions and the following disclaimer.
-+ *
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in
-+ *    the documentation and/or other materials provided with the
-+ *    distribution.
-+ *
-+ * 3. The end-user documentation included with the redistribution,
-+ *    if any, must include the following acknowledgment:
-+ *       "This product includes software developed by the
-+ *        Apache Software Foundation (http://www.apache.org/)."
-+ *    Alternately, this acknowledgment may appear in the software itself,
-+ *    if and wherever such third-party acknowledgments normally appear.
-+ *
-+ * 4. The names "Apache" and "Apache Software Foundation" must
-+ *    not be used to endorse or promote products derived from this
-+ *    software without prior written permission. For written
-+ *    permission, please contact apache@apache.org.
-+ *
-+ * 5. Products derived from this software may not be called "Apache",
-+ *    nor may "Apache" appear in their name, without prior written
-+ *    permission of the Apache Software Foundation.
-+ *
-+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
-+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
-+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-+ * SUCH DAMAGE.
-+ * ====================================================================
-+ *
-+ * This software consists of voluntary contributions made by many
-+ * individuals on behalf of the Apache Software Foundation.  For more
-+ * information on the Apache Software Foundation, please see
-+ * <http://www.apache.org/>.
-+ *
-+ * Portions of this software are based upon public domain software
-+ * originally written at the National Center for Supercomputing Applications,
-+ * University of Illinois, Urbana-Champaign.
-+ */
-+
-+#include "httpd.h"
-+#include "mpm_default.h"
-+#include "scoreboard.h"
-+#include "unixd.h"
-+
-+#ifndef APACHE_MPM_PERUSER_H
-+#define APACHE_MPM_PERUSER_H
-+
-+#define PERUSER_MPM
-+
-+#define MPM_NAME "Peruser"
-+
-+#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
-+#define AP_MPM_WANT_WAIT_OR_TIMEOUT
-+#define AP_MPM_WANT_PROCESS_CHILD_STATUS
-+#define AP_MPM_WANT_SET_PIDFILE
-+#define AP_MPM_WANT_SET_SCOREBOARD
-+#define AP_MPM_WANT_SET_LOCKFILE
-+#define AP_MPM_WANT_SET_MAX_REQUESTS
-+#define AP_MPM_WANT_SET_COREDUMPDIR
-+#define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH
-+#define AP_MPM_WANT_SIGNAL_SERVER
-+#define AP_MPM_WANT_SET_MAX_MEM_FREE
-+#define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
-+
-+#define AP_MPM_USES_POD 1
-+#define MPM_CHILD_PID(i) (ap_scoreboard_image->parent[i].pid)
-+#define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
-+#define MPM_VALID_PID(p) (getpgid(p) == getpgrp())
-+#define MPM_ACCEPT_FUNC unixd_accept
-+
-+extern int ap_threads_per_child;
-+extern int ap_max_daemons_limit;
-+extern server_rec *ap_server_conf;
-+
-+/* Table of child status */
-+#define SERVER_DEAD 0
-+#define SERVER_DYING 1
-+#define SERVER_ALIVE 2
-+
-+typedef struct ap_ctable {
-+    pid_t pid;
-+    unsigned char status;
-+} ap_ctable;
-+
-+#endif /* APACHE_MPM_PERUSER_H */
-diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-peruser/server/mpm/experimental/peruser/peruser.c
---- httpd-2.2.13/server/mpm/experimental/peruser/peruser.c	1970-01-01 03:00:00.000000000 +0300
-+++ httpd-2.2.13-peruser/server/mpm/experimental/peruser/peruser.c	2009-09-10 11:52:39.000000000 +0300
-@@ -0,0 +1,3884 @@
+diff -ruN httpd-2.2.14/server/mpm/experimental/peruser/peruser.c peruser-0.4rc1/server/mpm/experimental/peruser/peruser.c
+--- httpd-2.2.14/server/mpm/experimental/peruser/peruser.c	1970-01-01 01:00:00.000000000 +0100
++++ peruser-0.4rc1/server/mpm/experimental/peruser/peruser.c	2009-11-21 22:02:27.000000000 +0100
+@@ -0,0 +1,3979 @@
 +
 +/* ====================================================================
 + * The Apache Software License, Version 1.1
@@ -1278,6 +1377,35 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +    return total;
 +}
 +
++static int active_processors(int child_num)
++{
++    int i, total;
++
++    for(i = 0, total = 0; i < NUM_CHILDS; ++i)
++    {
++        if( (CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv) && (CHILD_INFO_TABLE[i].pid > 0 ) )
++            total++;
++    }
++
++    return total;
++}
++
++static int active_env_processors(int env_num)
++{
++    int i, total;
++
++    if(env_num >= NUM_SENV)
++      return -1;
++
++    for(i = 0, total = 0; i < NUM_CHILDS; ++i)
++    {
++        if((CHILD_INFO_TABLE[i].senv == &SENV[env_num]) && (CHILD_INFO_TABLE[i].pid > 0))
++            total++;
++    }
++
++    return total;
++}
++
 +static int idle_processors(int child_num)
 +{
 +    int i, total;
@@ -1294,6 +1422,20 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +    return total;
 +}
 +
++static int idle_env_processors(int env_num)
++{
++    int i, total;
++
++    for(i = 0, total = 0; i < NUM_CHILDS; ++i)
++    {
++        if(CHILD_INFO_TABLE[i].senv == &SENV[env_num] && (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY) )
++            total++;
++    }
++
++    return total;
++}
++
++
 +static int wait_for_workers(child_info_t *processor) {
 +    int i, wait_step_size, wait_time;
 +    
@@ -1469,7 +1611,7 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +    child_info_t *processor;
 +    apr_pool_t *ptrans;
 +    peruser_server_conf *sconf;
-+    int ssl_on;
++    int ssl_on = 0;
 +
 +    _DBG("Creating dummy connection to use the vhost lookup api", 0);
 +
@@ -1481,12 +1623,11 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +        ap_update_vhost_given_ip(current_conn);
 +        _DBG("Base server is %s, name based vhosts %s", current_conn->base_server->server_hostname,
 +             current_conn->vhost_lookup_data ? "on" : "off");
++        
++        // check for ssl configuration for this server (ssl_server_is_https is NULL if we have no mod_ssl)
++        if(ssl_server_is_https) ssl_on = ssl_server_is_https(current_conn->base_server);
 +    }
 +
-+    // check for ssl configuration for this server (ssl_server_is_https is NULL if we have no mod_ssl)
-+    if(ssl_server_is_https) ssl_on = ssl_server_is_https(current_conn->base_server);
-+    else ssl_on = 0;
-+
 +    if (current_conn && (!current_conn->vhost_lookup_data || ssl_on) && CHILD_INFO_TABLE[my_child_num].type == CHILD_TYPE_MULTIPLEXER) {
 +    	_DBG("We are not using name based vhosts (or SSL is enabled), we'll directly pass the socket.");
 +
@@ -2128,8 +2269,6 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +    return APR_SUCCESS;
 +}
 +
-+static const char* child_clone();
-+
 +static void child_main(int child_num_arg)
 +{
 +    apr_pool_t *ptrans;
@@ -2997,6 +3136,7 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +	}
 +
 +	perform_idle_server_maintenance(pconf);
++	
 +#ifdef TPF
 +        shutdown_pending = os_check_server(tpf_server_name);
 +        ap_check_signals();
@@ -3407,7 +3547,7 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +    senv.chroot = multiplexer_chroot;
 +    senv.cgroup = NULL;
 +    senv.nice_lvl = 0;
-+    senv.name = NULL;
++    senv.name = "Multiplexer";
 +
 +    senv.min_processors 	= ap_min_multiplexers;
 +    senv.min_free_processors 	= ap_min_free_processors;
@@ -3565,6 +3705,12 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +    return OK;
 +}
 +
++
++int senv_active_cmp(const void *a, const void *b) {
++  _DBG("CMP %d %d", *(int *) a,*(int *)  b);
++  return active_env_processors(*(int *)a)<active_env_processors(*(int *)b);
++}
++
 +static int peruser_status_hook(request_rec *r, int flags)
 +{
 +    int x;
@@ -3572,45 +3718,77 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +
 +    if (flags & AP_STATUS_SHORT)
 +           return OK;
-+    
++
++
++	if (flags & AP_STATUS_STATS) {
++		
++		int *sorted_senv;
++		int i;
++		sorted_senv=(int *) apr_palloc(r->pool, NUM_SENV*sizeof(int));
++		
++		if(!sorted_senv) {
++			ap_rputs("peruser_status_hook(): Out of memory",r);
++			return OK;
++		}
++		/* Initial senv table */
++		for(i=0; i < NUM_SENV; i++)
++			sorted_senv[i]=i;
++
++		/* sort env by number of processors */
++		qsort(sorted_senv, NUM_SENV, sizeof(int), senv_active_cmp);
++
++		ap_rputs("<h3>Processors statistics:</h3><table border=\"0\"><tr><th>Environment</th><th>Pss</th><th>Avail</th></tr>", r);
++		/* just a mockup to se what data will be usefull here will put code layter, yes I know we need to iterate ON ENV[] NUM_ENV times */
++		for (x = 0; x < NUM_SENV; x++)
++	        {
++			senv = &SENV[sorted_senv[x]];
++			if(senv==NULL)
++				continue;
++			ap_rprintf(r, "<tr><td nowrap>%s</td><td nowrap>%d/%d/%d</td>"
++					"<td>%d%%</td></tr>",
++					senv == NULL ? NULL : ( senv->name == NULL ? "" : senv->name ),
++					active_env_processors(sorted_senv[x]), idle_env_processors(sorted_senv[x]), senv == NULL ? 0 : senv->max_processors,
++					senv == NULL ? 0 : senv->availability );
++			}
++			ap_rputs("</table><tr/>", r);
++			
++			ap_rputs("<hr/><table>"
++		 			"<tr><th>Pss</th><td>Number of processors active/idle/max</td></tr>"
++					"</table><hr/>",r);
++	}else {
 +    ap_rputs("<hr>\n", r);
-+    ap_rputs("<h2>peruser status</h2>\n", r);
++    ap_rputs("<h3>peruser status</h3>\n", r);
 +    ap_rputs("<table border=\"0\">\n", r);
-+    ap_rputs("<tr><td>ID</td><td>PID</td><td>STATUS</td><td>SB STATUS</td><td>TYPE</td><td>UID</td>"
-+                   "<td>GID</td><td>CHROOT</td><td>NICE</td><td>INPUT</td>"
-+                   "<td>OUTPUT</td><td>SOCK_FD</td>"
-+                   "<td>TOTAL PROCESSORS</td><td>MAX PROCESSORS</td>"
-+                   "<td>IDLE PROCESSORS</td><td>MIN FREE PROCESSORS</td>"
-+                   "<td>AVAIL</td>"
++    ap_rputs("<tr><th>ID</th><th>PID</th><th>STATUS</th><th>SB STATUS</th><th>Type</th><th>Processor</th>"
++                   "<th>Pss</th>"
++                   "<th>AVAIL</th>"
 +                   "</tr>\n", r);
 +    for (x = 0; x < NUM_CHILDS; x++)
 +        {
 +        senv = CHILD_INFO_TABLE[x].senv;
-+        ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%8s</td><td>%12s</td>"
-+                       "<td>%4d</td><td>%4d</td><td>%25s</td><td>%3d</td><td>%5d</td>"
-+                       "<td>%6d</td><td>%7d</td><td>%d</td><td>%d</td>"
-+                       "<td>%d</td><td>%d</td><td>%3d</td></tr>\n",
++        ap_rprintf(r, "<tr><td>%3d</td><td>%5d</td><td>%8s</td><td>%8s</td><td>%12s</td><td nowrap>%48s</td>"
++                       "<td>%d/%d/%d</td>"
++                       "<td>%3d%%</td></tr>\n",
 +                       CHILD_INFO_TABLE[x].id, 
 +                       CHILD_INFO_TABLE[x].pid, 
 +                       child_status_string(CHILD_INFO_TABLE[x].status), 
 +                       scoreboard_status_string(SCOREBOARD_STATUS(x)),
 +                       child_type_string(CHILD_INFO_TABLE[x].type), 
-+                       senv == NULL ? -1 : senv->uid, 
-+                       senv == NULL ? -1 : senv->gid, 
-+                       senv == NULL ? NULL : senv->chroot, 
-+                       senv == NULL ? 0 : senv->nice_lvl,
-+                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->input, 
-+                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->output, 
-+                       CHILD_INFO_TABLE[x].sock_fd,
-+                       total_processors(x), 
-+                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->max_processors,
++                       senv == NULL ? NULL : ( senv->name == NULL ? "" : senv->name ), 
++                       active_processors(x),
 +                       idle_processors(x),
-+                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->min_free_processors,
-+                       senv == NULL ? -1 : CHILD_INFO_TABLE[x].senv->availability
++                       senv == NULL ? 0 : CHILD_INFO_TABLE[x].senv->max_processors,
++                       senv == NULL ? 0 : CHILD_INFO_TABLE[x].senv->availability
 +                       );
 +       }
 +    ap_rputs("</table>\n", r);
-+    
++
++    ap_rputs("<hr/><table>"
++ 			"<tr><th>STATUS</th><td>Processor status</td></tr>"
++ 			"<tr><th>Pss</th><td>Number of processors active/idle/max</td></tr>"
++			"</table><hr/>",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);
@@ -3960,7 +4138,11 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +
 +    if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
 +        sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
-+        sconf->senv->min_processors = min_procs;
++        if(sconf->senv != NULL)
++			sconf->senv->min_processors = min_procs;
++		else
++			ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++	                     "WARNING: MinProcessors must be set after ServerEnvironment to take effect");
 +    }
 +    else {
 +        ap_min_processors = min_procs;
@@ -3989,7 +4171,11 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +
 +    if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
 +        sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
-+        sconf->senv->min_free_processors = min_free_procs;
++        if(sconf->senv != NULL)
++			sconf->senv->min_free_processors = min_free_procs;
++		else
++			ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++	                     "WARNING: MinSpareProcessors must be set after ServerEnvironment to take effect");
 +    }
 +    else {
 +        ap_min_free_processors = min_free_procs;
@@ -4018,7 +4204,11 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +
 +     if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
 +         sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
-+         sconf->senv->max_free_processors = max_free_procs;
++		 if(sconf!=NULL)
++			sconf->senv->max_free_processors = max_free_procs;
++		 else
++			ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++	                     "WARNING: MaxSpareProcessors must be set after ServerEnvironment to take effect");
 +     }
 +     else {
 +         ap_max_free_processors = max_free_procs;
@@ -4047,7 +4237,11 @@ diff -Nur httpd-2.2.13/server/mpm/experimental/peruser/peruser.c httpd-2.2.13-pe
 +
 +    if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
 +        sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
-+        sconf->senv->max_processors = max_procs;
++		if(sconf->senv != NULL)
++        	sconf->senv->max_processors = max_procs;
++		else
++			ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
++	                     "WARNING: MaxProcessors must be set after ServerEnvironment to take effect");
 +    }
 +    else {
 +        ap_max_processors = max_procs;


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:33 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:33 UTC (permalink / raw
  To: gentoo-commits

commit:     bcd526b6e7807a78b1ab92c942a9ce10385faa90
Author:     Krzysztof Pawlik <nelchael <AT> gentoo <DOT> org>
AuthorDate: Wed Sep  1 08:07:51 2010 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Wed Sep  1 08:07:51 2010 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=bcd526b6

Add patch for APXS to respect LDFLAGS, see bug #335405.

---
 2.2/patches/10_all_apxs_ldflags.patch | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/2.2/patches/10_all_apxs_ldflags.patch b/2.2/patches/10_all_apxs_ldflags.patch
new file mode 100644
index 0000000..8fed52b
--- /dev/null
+++ b/2.2/patches/10_all_apxs_ldflags.patch
@@ -0,0 +1,13 @@
+diff -Nru httpd-2.2.16.orig/support/apxs.in httpd-2.2.16/support/apxs.in
+--- httpd-2.2.16.orig/support/apxs.in	2010-08-31 15:11:51.964281072 +0200
++++ httpd-2.2.16/support/apxs.in	2010-08-31 15:17:38.562895073 +0200
+@@ -430,6 +430,9 @@
+         $opt .= " -l$opt_l";
+     }
+ 
++    # Add LDFLAGS from environment:
++    $opt .= " $ENV{'LDFLAGS'}";
++
+     if ($opt_p == 1) {
+         
+         my $apr_libs=`$apr_config --cflags --ldflags --link-libtool --libs`;


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:33 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:33 UTC (permalink / raw
  To: gentoo-commits

commit:     7d606c717370e55710be5f9c339c047131c38c38
Author:     Peter Volkov <pva <AT> gentoo <DOT> org>
AuthorDate: Thu Sep 15 10:11:45 2011 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Thu Sep 15 10:11:45 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=7d606c71

Don't install craft into /etc/apache2, bug 382997 wrt Remy Blank

---
 2.2/patches/03_all_gentoo_apache-tools.patch | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/2.2/patches/03_all_gentoo_apache-tools.patch b/2.2/patches/03_all_gentoo_apache-tools.patch
index 4ac4253..311c91a 100644
--- a/2.2/patches/03_all_gentoo_apache-tools.patch
+++ b/2.2/patches/03_all_gentoo_apache-tools.patch
@@ -1,15 +1,6 @@
 diff -pruN a/Makefile.in b/Makefile.in
 --- a/Makefile.in	2011-08-24 00:34:55.000000000 +0300
 +++ b/Makefile.in	2011-08-24 00:29:01.000000000 +0300
-@@ -14,7 +14,7 @@ PROGRAM_DEPENDENCIES = \
- 
- PROGRAMS        = $(PROGRAM_NAME)
- TARGETS         = $(PROGRAMS) $(shared_build) $(other_targets)
--INSTALL_TARGETS = install-htdocs install-error install-icons \
-+INSTALL_TARGETS = install-conf install-htdocs install-error install-icons \
- 	install-other install-cgi install-include install-suexec install-build \
- 	install-man
- 
 @@ -202,14 +202,20 @@ install-include:
  	  $(INSTALL_DATA) $$hdr $(DESTDIR)$(includedir); \
  	done


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 15:33 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 15:33 UTC (permalink / raw
  To: gentoo-commits

commit:     f77f8958d181ddf877dea7d373ed8cdbda006dd3
Author:     Peter Volkov <pva <AT> gentoo <DOT> org>
AuthorDate: Tue Oct 18 06:12:18 2011 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Tue Oct 18 06:12:18 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=f77f8958

Patch to fix Reverse Proxy Mode Security Bypass (CVE-2011-3368).

---
 .../25_all-apply_to_2.2.21-CVE-2011-3368.patch     | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/2.2/patches/25_all-apply_to_2.2.21-CVE-2011-3368.patch b/2.2/patches/25_all-apply_to_2.2.21-CVE-2011-3368.patch
new file mode 100644
index 0000000..e8125d9
--- /dev/null
+++ b/2.2/patches/25_all-apply_to_2.2.21-CVE-2011-3368.patch
@@ -0,0 +1,34 @@
+
+SECURITY (CVE-2011-3368): Prevent unintended pattern expansion in some
+reverse proxy configurations by strictly validating the request-URI.
+
+http://svn.apache.org/viewvc?rev=1179239&view=rev
+
+--- httpd-2.2.21/server/protocol.c
++++ httpd-2.2.21/server/protocol.c
+@@ -640,6 +640,25 @@
+ 
+     ap_parse_uri(r, uri);
+ 
++    /* RFC 2616:
++     *   Request-URI    = "*" | absoluteURI | abs_path | authority
++     *
++     * authority is a special case for CONNECT.  If the request is not
++     * using CONNECT, and the parsed URI does not have scheme, and
++     * it does not begin with '/', and it is not '*', then, fail
++     * and give a 400 response. */
++    if (r->method_number != M_CONNECT 
++        && !r->parsed_uri.scheme 
++        && uri[0] != '/'
++        && !(uri[0] == '*' && uri[1] == '\0')) {
++        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
++                      "invalid request-URI %s", uri);
++        r->args = NULL;
++        r->hostname = NULL;
++        r->status = HTTP_BAD_REQUEST;
++        r->uri = apr_pstrdup(r->pool, uri);
++    }
++
+     if (ll[0]) {
+         r->assbackwards = 0;
+         pro = ll;


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2013-11-09 21:23 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2013-11-09 21:23 UTC (permalink / raw
  To: gentoo-commits

commit:     8bd93896b5234bb6fd552fe5ec954b311c904998
Author:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
AuthorDate: Sat Nov  9 21:23:05 2013 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Sat Nov  9 21:23:05 2013 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=8bd93896

Fix runtimedir as well.

---
 2.2/patches/config.layout | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/2.2/patches/config.layout b/2.2/patches/config.layout
index 83a4b0f..f8debc4 100644
--- a/2.2/patches/config.layout
+++ b/2.2/patches/config.layout
@@ -16,7 +16,7 @@
 	manualdir:       /usr/share/doc/version/manual
 	sysconfdir:      /etc/apache2
 	localstatedir:   /var
-	runtimedir:      /var/run
+	runtimedir:      /run
 	logfiledir:      /var/log/apache2
 	proxycachedir:   /var/cache/apache2
 </Layout>


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2014-07-31 11:25 Lars Wendler
  2014-08-24  9:46 ` Lars Wendler
  0 siblings, 1 reply; 17+ messages in thread
From: Lars Wendler @ 2014-07-31 11:25 UTC (permalink / raw
  To: gentoo-commits

commit:     b863adc76dbc98a303c0246c09f1038148f30451
Author:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
AuthorDate: Thu Jul 31 11:24:35 2014 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Thu Jul 31 11:24:35 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=b863adc7

Added several security fixes (CVE-2014-0118, CVE-2014-0226 and CVE-2014-0231)

---
 2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch    | 309 +++++++++++++++++++++
 2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch    | 137 +++++++++
 2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch    | 165 +++++++++++
 ....0-rc2.patch => 30_all_peruser_0.4.0-rc2.patch} |   2 +-
 4 files changed, 612 insertions(+), 1 deletion(-)

diff --git a/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch b/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch
new file mode 100644
index 0000000..6db06ba
--- /dev/null
+++ b/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch
@@ -0,0 +1,309 @@
+Author: jim
+Date: Thu Jul 17 18:20:46 2014
+New Revision: 1611426
+
+URL: http://svn.apache.org/r1611426
+Log:
+Merge r1610501 from trunk:
+
+  *) SECURITY: CVE-2014-0118 (cve.mitre.org)
+     mod_deflate: The DEFLATE input filter (inflates request bodies) now
+     limits the length and compression ratio of inflated request bodies to avoid
+     denial of sevice via highly compressed bodies.  See directives 
+     DeflateInflateLimitRequestBody, DeflateInflateRatioLimit,
+     and DeflateInflateRatioBurst.
+
+Thanks to Giancarlo Pellegrino and Davide Balzarotti for reporting the issue.
+
+Submitted By: ylavic, covener
+Reviewed By: jorton, covener, jim
+
+
+
+Submitted by: covener
+Reviewed/backported by: jim
+
+Modified:
+    httpd/httpd/branches/2.2.x/   (props changed)
+    httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c
+
+Propchange: httpd/httpd/branches/2.2.x/
+------------------------------------------------------------------------------
+  Merged /httpd/httpd/trunk:r1610501
+
+Modified: httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c?rev=1611426&r1=1611425&r2=1611426&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c (original)
++++ httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c Thu Jul 17 18:20:46 2014
+@@ -37,6 +37,7 @@
+ #include "httpd.h"
+ #include "http_config.h"
+ #include "http_log.h"
++#include "http_core.h"
+ #include "apr_lib.h"
+ #include "apr_strings.h"
+ #include "apr_general.h"
+@@ -51,6 +52,9 @@
+ static const char deflateFilterName[] = "DEFLATE";
+ module AP_MODULE_DECLARE_DATA deflate_module;
+ 
++#define AP_INFLATE_RATIO_LIMIT 200
++#define AP_INFLATE_RATIO_BURST 3
++
+ typedef struct deflate_filter_config_t
+ {
+     int windowSize;
+@@ -62,6 +66,12 @@ typedef struct deflate_filter_config_t
+     char *note_output_name;
+ } deflate_filter_config;
+ 
++typedef struct deflate_dirconf_t {
++    apr_off_t inflate_limit;
++    int ratio_limit,
++        ratio_burst;
++} deflate_dirconf_t;
++
+ /* RFC 1952 Section 2.3 defines the gzip header:
+  *
+  * +---+---+---+---+---+---+---+---+---+---+
+@@ -193,6 +203,14 @@ static void *create_deflate_server_confi
+     return c;
+ }
+ 
++static void *create_deflate_dirconf(apr_pool_t *p, char *dummy)
++{
++    deflate_dirconf_t *dc = apr_pcalloc(p, sizeof(*dc));
++    dc->ratio_limit = AP_INFLATE_RATIO_LIMIT;
++    dc->ratio_burst = AP_INFLATE_RATIO_BURST;
++    return dc;
++}
++
+ static const char *deflate_set_window_size(cmd_parms *cmd, void *dummy,
+                                            const char *arg)
+ {
+@@ -284,6 +302,55 @@ static const char *deflate_set_compressi
+     return NULL;
+ }
+ 
++
++static const char *deflate_set_inflate_limit(cmd_parms *cmd, void *dirconf,
++                                      const char *arg)
++{
++    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
++    char *errp;
++
++    if (APR_SUCCESS != apr_strtoff(&dc->inflate_limit, arg, &errp, 10)) {
++        return "DeflateInflateLimitRequestBody is not parsable.";
++    }
++    if (*errp || dc->inflate_limit < 0) {
++        return "DeflateInflateLimitRequestBody requires a non-negative integer.";
++    }
++
++    return NULL;
++}
++
++static const char *deflate_set_inflate_ratio_limit(cmd_parms *cmd,
++                                                   void *dirconf,
++                                                   const char *arg)
++{
++    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
++    int i;
++
++    i = atoi(arg);
++    if (i <= 0)
++        return "DeflateInflateRatioLimit must be positive";
++
++    dc->ratio_limit = i;
++
++    return NULL;
++}
++
++static const char *deflate_set_inflate_ratio_burst(cmd_parms *cmd,
++                                                   void *dirconf,
++                                                   const char *arg)
++{
++    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
++    int i;
++
++    i = atoi(arg);
++    if (i <= 0)
++        return "DeflateInflateRatioBurst must be positive";
++
++    dc->ratio_burst = i;
++
++    return NULL;
++}
++
+ typedef struct deflate_ctx_t
+ {
+     z_stream stream;
+@@ -294,8 +361,26 @@ typedef struct deflate_ctx_t
+     unsigned char *validation_buffer;
+     apr_size_t validation_buffer_length;
+     int inflate_init;
++    int ratio_hits;
++    apr_off_t inflate_total;
+ } deflate_ctx;
+ 
++/* Check whether the (inflate) ratio exceeds the configured limit/burst. */
++static int check_ratio(request_rec *r, deflate_ctx *ctx,
++                       const deflate_dirconf_t *dc)
++{
++    if (ctx->stream.total_in) {
++        int ratio = ctx->stream.total_out / ctx->stream.total_in;
++        if (ratio < dc->ratio_limit) {
++            ctx->ratio_hits = 0;
++        }
++        else if (++ctx->ratio_hits > dc->ratio_burst) {
++            return 0;
++        }
++    }
++    return 1;
++}
++
+ /* Number of validation bytes (CRC and length) after the compressed data */
+ #define VALIDATION_SIZE 8
+ /* Do not update ctx->crc, see comment in flush_libz_buffer */
+@@ -744,6 +829,8 @@ static apr_status_t deflate_in_filter(ap
+     int zRC;
+     apr_status_t rv;
+     deflate_filter_config *c;
++    deflate_dirconf_t *dc;
++    apr_off_t inflate_limit;
+ 
+     /* just get out of the way of things we don't want. */
+     if (mode != AP_MODE_READBYTES) {
+@@ -751,6 +838,7 @@ static apr_status_t deflate_in_filter(ap
+     }
+ 
+     c = ap_get_module_config(r->server->module_config, &deflate_module);
++    dc = ap_get_module_config(r->per_dir_config, &deflate_module);
+ 
+     if (!ctx) {
+         char deflate_hdr[10];
+@@ -803,11 +891,13 @@ static apr_status_t deflate_in_filter(ap
+         if (len != 10 ||
+             deflate_hdr[0] != deflate_magic[0] ||
+             deflate_hdr[1] != deflate_magic[1]) {
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Failed to inflate input: wrong/partial magic bytes");
+             return APR_EGENERAL;
+         }
+ 
+         /* We can't handle flags for now. */
+         if (deflate_hdr[3] != 0) {
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Failed to inflate input: cannot handle deflate flags");
+             return APR_EGENERAL;
+         }
+ 
+@@ -831,6 +921,12 @@ static apr_status_t deflate_in_filter(ap
+         apr_brigade_cleanup(ctx->bb);
+     }
+ 
++    inflate_limit = dc->inflate_limit; 
++    if (inflate_limit == 0) { 
++        /* The core is checking the deflated body, we'll check the inflated */
++        inflate_limit = ap_get_limit_req_body(f->r);
++    }
++
+     if (APR_BRIGADE_EMPTY(ctx->proc_bb)) {
+         rv = ap_get_brigade(f->next, ctx->bb, mode, block, readbytes);
+ 
+@@ -863,6 +959,17 @@ static apr_status_t deflate_in_filter(ap
+ 
+                 ctx->stream.next_out = ctx->buffer;
+                 len = c->bufferSize - ctx->stream.avail_out;
++ 
++                ctx->inflate_total += len;
++                if (inflate_limit && ctx->inflate_total > inflate_limit) { 
++                    inflateEnd(&ctx->stream);
++                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
++                            "Inflated content length of %" APR_OFF_T_FMT
++                            " is larger than the configured limit"
++                            " of %" APR_OFF_T_FMT, 
++                            ctx->inflate_total, inflate_limit);
++                    return APR_ENOSPC;
++                }
+ 
+                 ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
+                 tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
+@@ -891,6 +998,26 @@ static apr_status_t deflate_in_filter(ap
+                     ctx->stream.next_out = ctx->buffer;
+                     len = c->bufferSize - ctx->stream.avail_out;
+ 
++                      ctx->inflate_total += len;
++                      if (inflate_limit && ctx->inflate_total > inflate_limit) { 
++                          inflateEnd(&ctx->stream);
++                          ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
++                                  "Inflated content length of %" APR_OFF_T_FMT
++                                  " is larger than the configured limit"
++                                  " of %" APR_OFF_T_FMT, 
++                                  ctx->inflate_total, inflate_limit);
++                          return APR_ENOSPC;
++                      }
++
++                      if (!check_ratio(r, ctx, dc)) {
++                          inflateEnd(&ctx->stream);
++                          ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
++                                  "Inflated content ratio is larger than the "
++                                  "configured limit %i by %i time(s)",
++                                  dc->ratio_limit, dc->ratio_burst);
++                          return APR_EINVAL;
++                      }
++
+                     ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
+                     tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
+                                                       NULL, f->c->bucket_alloc);
+@@ -1003,6 +1130,7 @@ static apr_status_t inflate_out_filter(a
+     int zRC;
+     apr_status_t rv;
+     deflate_filter_config *c;
++    deflate_dirconf_t *dc;
+ 
+     /* Do nothing if asked to filter nothing. */
+     if (APR_BRIGADE_EMPTY(bb)) {
+@@ -1010,6 +1138,7 @@ static apr_status_t inflate_out_filter(a
+     }
+ 
+     c = ap_get_module_config(r->server->module_config, &deflate_module);
++    dc = ap_get_module_config(r->per_dir_config, &deflate_module);
+ 
+     if (!ctx) {
+ 
+@@ -1272,6 +1401,14 @@ static apr_status_t inflate_out_filter(a
+         while (ctx->stream.avail_in != 0) {
+             if (ctx->stream.avail_out == 0) {
+ 
++                if (!check_ratio(r, ctx, dc)) {
++                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
++                            "Inflated content ratio is larger than the "
++                            "configured limit %i by %i time(s)",
++                            dc->ratio_limit, dc->ratio_burst);
++                    return APR_EINVAL;
++                }
++
+                 ctx->stream.next_out = ctx->buffer;
+                 len = c->bufferSize - ctx->stream.avail_out;
+ 
+@@ -1346,12 +1483,20 @@ static const command_rec deflate_filter_
+                   "Set the Deflate Memory Level (1-9)"),
+     AP_INIT_TAKE1("DeflateCompressionLevel", deflate_set_compressionlevel, NULL, RSRC_CONF,
+                   "Set the Deflate Compression Level (1-9)"),
++    AP_INIT_TAKE1("DeflateInflateLimitRequestBody", deflate_set_inflate_limit, NULL, OR_ALL,
++                  "Set a limit on size of inflated input"),
++    AP_INIT_TAKE1("DeflateInflateRatioLimit", deflate_set_inflate_ratio_limit, NULL, OR_ALL,
++                  "Set the inflate ratio limit above which inflation is "
++                  "aborted (default: " APR_STRINGIFY(AP_INFLATE_RATIO_LIMIT) ")"),
++    AP_INIT_TAKE1("DeflateInflateRatioBurst", deflate_set_inflate_ratio_burst, NULL, OR_ALL,
++                  "Set the maximum number of following inflate ratios above limit "
++                  "(default: " APR_STRINGIFY(AP_INFLATE_RATIO_BURST) ")"),
+     {NULL}
+ };
+ 
+ module AP_MODULE_DECLARE_DATA deflate_module = {
+     STANDARD20_MODULE_STUFF,
+-    NULL,                         /* dir config creater */
++    create_deflate_dirconf,       /* dir config creater */
+     NULL,                         /* dir merger --- default is to override */
+     create_deflate_server_config, /* server config */
+     NULL,                         /* merge server config */

diff --git a/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch b/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch
new file mode 100644
index 0000000..51f974e
--- /dev/null
+++ b/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch
@@ -0,0 +1,137 @@
+Author: jorton
+Date: Mon Jul 14 20:34:32 2014
+New Revision: 1610515
+
+URL: http://svn.apache.org/r1610515
+Log:
+Merge 1610491 from trunk:
+
+SECURITY (CVE-2014-0226): Fix a race condition in scoreboard handling,
+which could lead to a heap buffer overflow.  Thanks to Marek Kroemeke
+working with HP's Zero Day Initiative for reporting this.
+
+* include/scoreboard.h: Add ap_copy_scoreboard_worker.
+
+* server/scoreboard.c (ap_copy_scoreboard_worker): New function.
+
+* modules/generators/mod_status.c (status_handler): Use it.
+
+Reviewed by: trawick, jorton, covener
+Submitted by: jorton, trawick, covener
+
+Modified:
+    httpd/httpd/branches/2.2.x/   (props changed)
+    httpd/httpd/branches/2.2.x/include/ap_mmn.h
+    httpd/httpd/branches/2.2.x/include/scoreboard.h
+    httpd/httpd/branches/2.2.x/modules/generators/mod_status.c
+    httpd/httpd/branches/2.2.x/server/scoreboard.c
+
+Propchange: httpd/httpd/branches/2.2.x/
+------------------------------------------------------------------------------
+  Merged /httpd/httpd/trunk:r1610491
+
+Modified: httpd/httpd/branches/2.2.x/include/ap_mmn.h
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/ap_mmn.h?rev=1610515&r1=1610514&r2=1610515&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/include/ap_mmn.h (original)
++++ httpd/httpd/branches/2.2.x/include/ap_mmn.h Mon Jul 14 20:34:32 2014
+@@ -151,6 +151,7 @@
+  * 20051115.31 (2.2.23) Add forcerecovery to proxy_balancer_shared struct
+  * 20051115.32 (2.2.24) Add ap_get_exec_line
+  * 20051115.33 (2.2.24) Add ap_pregsub_ex()
++ * 20051115.34 (2.2.28) Add ap_copy_scoreboard_worker()
+  */
+ 
+ #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
+@@ -158,7 +159,7 @@
+ #ifndef MODULE_MAGIC_NUMBER_MAJOR
+ #define MODULE_MAGIC_NUMBER_MAJOR 20051115
+ #endif
+-#define MODULE_MAGIC_NUMBER_MINOR 33                    /* 0...n */
++#define MODULE_MAGIC_NUMBER_MINOR 34                    /* 0...n */
+ 
+ /**
+  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
+
+Modified: httpd/httpd/branches/2.2.x/include/scoreboard.h
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/scoreboard.h?rev=1610515&r1=1610514&r2=1610515&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/include/scoreboard.h (original)
++++ httpd/httpd/branches/2.2.x/include/scoreboard.h Mon Jul 14 20:34:32 2014
+@@ -189,7 +189,24 @@ AP_DECLARE(int) ap_update_child_status_f
+                                                     int status, request_rec *r);
+ void ap_time_process_request(ap_sb_handle_t *sbh, int status);
+ 
++/** Return a pointer to the worker_score for a given child, thread pair.
++ * @param child_num The child number.
++ * @param thread_num The thread number.
++ * @return A pointer to the worker_score structure.
++ * @deprecated This function is deprecated, use ap_copy_scoreboard_worker instead. 
++ */
+ AP_DECLARE(worker_score *) ap_get_scoreboard_worker(int x, int y);
++
++/** Copy the contents of a worker's scoreboard entry.  The contents of
++ * the worker_score structure are copied verbatim into the dest
++ * structure.
++ * @param dest Output parameter.
++ * @param child_num The child number.
++ * @param thread_num The thread number.
++ */
++AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest,
++                                           int child_num, int thread_num);
++
+ AP_DECLARE(process_score *) ap_get_scoreboard_process(int x);
+ AP_DECLARE(global_score *) ap_get_scoreboard_global(void);
+ AP_DECLARE(lb_score *) ap_get_scoreboard_lb(int lb_num);
+
+Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_status.c
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_status.c?rev=1610515&r1=1610514&r2=1610515&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/modules/generators/mod_status.c (original)
++++ httpd/httpd/branches/2.2.x/modules/generators/mod_status.c Mon Jul 14 20:34:32 2014
+@@ -241,7 +241,7 @@ static int status_handler(request_rec *r
+ #endif
+     int short_report;
+     int no_table_report;
+-    worker_score *ws_record;
++    worker_score *ws_record = apr_palloc(r->pool, sizeof *ws_record);
+     process_score *ps_record;
+     char *stat_buffer;
+     pid_t *pid_buffer, worker_pid;
+@@ -333,7 +333,7 @@ static int status_handler(request_rec *r
+         for (j = 0; j < thread_limit; ++j) {
+             int indx = (i * thread_limit) + j;
+ 
+-            ws_record = ap_get_scoreboard_worker(i, j);
++            ap_copy_scoreboard_worker(ws_record, i, j);
+             res = ws_record->status;
+             stat_buffer[indx] = status_flags[res];
+ 
+
+Modified: httpd/httpd/branches/2.2.x/server/scoreboard.c
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/scoreboard.c?rev=1610515&r1=1610514&r2=1610515&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/server/scoreboard.c (original)
++++ httpd/httpd/branches/2.2.x/server/scoreboard.c Mon Jul 14 20:34:32 2014
+@@ -510,6 +510,21 @@ AP_DECLARE(worker_score *) ap_get_scoreb
+     return &ap_scoreboard_image->servers[x][y];
+ }
+ 
++AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest, 
++                                           int child_num,
++                                           int thread_num)
++{
++    worker_score *ws = ap_get_scoreboard_worker(child_num, thread_num);
++
++    memcpy(dest, ws, sizeof *ws);
++
++    /* For extra safety, NUL-terminate the strings returned, though it
++     * should be true those last bytes are always zero anyway. */
++    dest->client[sizeof(dest->client) - 1] = '\0';
++    dest->request[sizeof(dest->request) - 1] = '\0';
++    dest->vhost[sizeof(dest->vhost) - 1] = '\0';
++}
++
+ AP_DECLARE(process_score *) ap_get_scoreboard_process(int x)
+ {
+     if ((x < 0) || (server_limit < x)) {

diff --git a/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch b/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch
new file mode 100644
index 0000000..e7911e0
--- /dev/null
+++ b/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch
@@ -0,0 +1,165 @@
+Author: wrowe
+Date: Wed Jul 16 20:56:51 2014
+New Revision: 1611185
+
+URL: http://svn.apache.org/r1611185
+Log:
+SECURITY: CVE-2014-0231
+
+  mod_cgid: Fix a denial of service against CGI scripts that do
+  not consume stdin that could lead to lingering HTTPD child processes
+  filling up the scoreboard and eventually hanging the server.
+
+Submitted by: Rainer Jung, Eric Covener, Yann Ylavic
+Backports: r1610509, r1535125
+Reviewed by: covener, trawick, ylavic
+
+Modified:
+    httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c
+
+Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c?rev=1611185&r1=1611184&r2=1611185&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c (original)
++++ httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c Wed Jul 16 20:56:51 2014
+@@ -93,6 +93,10 @@ static const char *sockname;
+ static pid_t parent_pid;
+ static ap_unix_identity_t empty_ugid = { (uid_t)-1, (gid_t)-1, -1 };
+ 
++typedef struct { 
++    apr_interval_time_t timeout;
++} cgid_dirconf;
++
+ /* The APR other-child API doesn't tell us how the daemon exited
+  * (SIGSEGV vs. exit(1)).  The other-child maintenance function
+  * needs to decide whether to restart the daemon after a failure
+@@ -934,7 +938,14 @@ static void *merge_cgid_config(apr_pool_
+     return overrides->logname ? overrides : base;
+ }
+ 
++static void *create_cgid_dirconf(apr_pool_t *p, char *dummy)
++{
++    cgid_dirconf *c = (cgid_dirconf *) apr_pcalloc(p, sizeof(cgid_dirconf));
++    return c;
++}
++
+ static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
++
+ {
+     server_rec *s = cmd->server;
+     cgid_server_conf *conf = ap_get_module_config(s->module_config,
+@@ -987,7 +998,16 @@ static const char *set_script_socket(cmd
+ 
+     return NULL;
+ }
++static const char *set_script_timeout(cmd_parms *cmd, void *dummy, const char *arg)
++{
++    cgid_dirconf *dc = dummy;
+ 
++    if (ap_timeout_parameter_parse(arg, &dc->timeout, "s") != APR_SUCCESS) { 
++        return "CGIDScriptTimeout has wrong format";
++    }
++ 
++    return NULL;
++}
+ static const command_rec cgid_cmds[] =
+ {
+     AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
+@@ -999,6 +1019,10 @@ static const command_rec cgid_cmds[] =
+     AP_INIT_TAKE1("ScriptSock", set_script_socket, NULL, RSRC_CONF,
+                   "the name of the socket to use for communication with "
+                   "the cgi daemon."),
++    AP_INIT_TAKE1("CGIDScriptTimeout", set_script_timeout, NULL, RSRC_CONF | ACCESS_CONF,
++                  "The amount of time to wait between successful reads from "
++                  "the CGI script, in seconds."),
++                  
+     {NULL}
+ };
+ 
+@@ -1335,11 +1359,15 @@ static int cgid_handler(request_rec *r)
+     apr_file_t *tempsock;
+     struct cleanup_script_info *info;
+     apr_status_t rv;
++    cgid_dirconf *dc;
+ 
+     if (strcmp(r->handler,CGI_MAGIC_TYPE) && strcmp(r->handler,"cgi-script"))
+         return DECLINED;
+ 
+     conf = ap_get_module_config(r->server->module_config, &cgid_module);
++    dc = ap_get_module_config(r->per_dir_config, &cgid_module);
++
++    
+     is_included = !strcmp(r->protocol, "INCLUDED");
+ 
+     if ((argv0 = strrchr(r->filename, '/')) != NULL)
+@@ -1412,6 +1440,12 @@ static int cgid_handler(request_rec *r)
+      */
+ 
+     apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
++    if (dc->timeout > 0) { 
++        apr_file_pipe_timeout_set(tempsock, dc->timeout);
++    }
++    else { 
++        apr_file_pipe_timeout_set(tempsock, r->server->timeout);
++    }
+     apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
+ 
+     if ((argv0 = strrchr(r->filename, '/')) != NULL)
+@@ -1487,6 +1521,10 @@ static int cgid_handler(request_rec *r)
+             if (rv != APR_SUCCESS) {
+                 /* silly script stopped reading, soak up remaining message */
+                 child_stopped_reading = 1;
++                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, 
++                              "Error writing request body to script %s", 
++                              r->filename);
++
+             }
+         }
+         apr_brigade_cleanup(bb);
+@@ -1577,7 +1615,13 @@ static int cgid_handler(request_rec *r)
+             return HTTP_MOVED_TEMPORARILY;
+         }
+ 
+-        ap_pass_brigade(r->output_filters, bb);
++        rv = ap_pass_brigade(r->output_filters, bb);
++        if (rv != APR_SUCCESS) { 
++            /* APLOG_ERR because the core output filter message is at error,
++             * but doesn't know it's passing CGI output 
++             */
++            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "Failed to flush CGI output to client");
++        }
+     }
+ 
+     if (nph) {
+@@ -1707,6 +1751,8 @@ static int include_cmd(include_ctx_t *ct
+     request_rec *r = f->r;
+     cgid_server_conf *conf = ap_get_module_config(r->server->module_config,
+                                                   &cgid_module);
++    cgid_dirconf *dc = ap_get_module_config(r->per_dir_config, &cgid_module);
++
+     struct cleanup_script_info *info;
+ 
+     add_ssi_vars(r);
+@@ -1736,6 +1782,13 @@ static int include_cmd(include_ctx_t *ct
+      * get rid of the cleanup we registered when we created the socket.
+      */
+     apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
++    if (dc->timeout > 0) {
++        apr_file_pipe_timeout_set(tempsock, dc->timeout);
++    }
++    else {
++        apr_file_pipe_timeout_set(tempsock, r->server->timeout);
++    }
++
+     apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
+ 
+     APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pipe_create(tempsock,
+@@ -1841,7 +1894,7 @@ static void register_hook(apr_pool_t *p)
+ 
+ module AP_MODULE_DECLARE_DATA cgid_module = {
+     STANDARD20_MODULE_STUFF,
+-    NULL, /* dir config creater */
++    create_cgid_dirconf, /* dir config creater */
+     NULL, /* dir merger --- default is to override */
+     create_cgid_config, /* server config */
+     merge_cgid_config, /* merge server config */

diff --git a/2.2/patches/20_all_peruser_0.4.0-rc2.patch b/2.2/patches/30_all_peruser_0.4.0-rc2.patch
similarity index 99%
rename from 2.2/patches/20_all_peruser_0.4.0-rc2.patch
rename to 2.2/patches/30_all_peruser_0.4.0-rc2.patch
index 6784c78..546d94a 100644
--- a/2.2/patches/20_all_peruser_0.4.0-rc2.patch
+++ b/2.2/patches/30_all_peruser_0.4.0-rc2.patch
@@ -30,7 +30,7 @@ diff -Nur httpd-2.2.16/modules/generators/mod_status.c httpd-2.2.16-peruser/modu
      int short_report;
      int no_table_report;
 +    int peruser_stats;
-     worker_score *ws_record;
+     worker_score *ws_record = apr_palloc(r->pool, sizeof *ws_record);
      process_score *ps_record;
      char *stat_buffer;
 @@ -268,6 +271,7 @@


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2014-07-31 11:29 Lars Wendler
  2014-08-24  9:46 ` Lars Wendler
  0 siblings, 1 reply; 17+ messages in thread
From: Lars Wendler @ 2014-07-31 11:29 UTC (permalink / raw
  To: gentoo-commits

commit:     835c73fc452dfda31d782e3021959b91e56fc96a
Author:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
AuthorDate: Thu Jul 31 11:29:25 2014 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Thu Jul 31 11:29:25 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=835c73fc

Move itk patch behind peruser patch

---
 2.2/patches/{21_all-itk-20110321.patch => 31_all-itk-20110321.patch} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

diff --git a/2.2/patches/21_all-itk-20110321.patch b/2.2/patches/31_all-itk-20110321.patch
similarity index 100%
rename from 2.2/patches/21_all-itk-20110321.patch
rename to 2.2/patches/31_all-itk-20110321.patch


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
  2014-07-31 11:25 Lars Wendler
@ 2014-08-24  9:46 ` Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2014-08-24  9:46 UTC (permalink / raw
  To: gentoo-commits

commit:     b863adc76dbc98a303c0246c09f1038148f30451
Author:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
AuthorDate: Thu Jul 31 11:24:35 2014 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Thu Jul 31 11:24:35 2014 +0000
URL:        http://sources.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=b863adc7

Added several security fixes (CVE-2014-0118, CVE-2014-0226 and CVE-2014-0231)

---
 2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch    | 309 +++++++++++++++++++++
 2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch    | 137 +++++++++
 2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch    | 165 +++++++++++
 ....0-rc2.patch => 30_all_peruser_0.4.0-rc2.patch} |   2 +-
 4 files changed, 612 insertions(+), 1 deletion(-)

diff --git a/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch b/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch
new file mode 100644
index 0000000..6db06ba
--- /dev/null
+++ b/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch
@@ -0,0 +1,309 @@
+Author: jim
+Date: Thu Jul 17 18:20:46 2014
+New Revision: 1611426
+
+URL: http://svn.apache.org/r1611426
+Log:
+Merge r1610501 from trunk:
+
+  *) SECURITY: CVE-2014-0118 (cve.mitre.org)
+     mod_deflate: The DEFLATE input filter (inflates request bodies) now
+     limits the length and compression ratio of inflated request bodies to avoid
+     denial of sevice via highly compressed bodies.  See directives 
+     DeflateInflateLimitRequestBody, DeflateInflateRatioLimit,
+     and DeflateInflateRatioBurst.
+
+Thanks to Giancarlo Pellegrino and Davide Balzarotti for reporting the issue.
+
+Submitted By: ylavic, covener
+Reviewed By: jorton, covener, jim
+
+
+
+Submitted by: covener
+Reviewed/backported by: jim
+
+Modified:
+    httpd/httpd/branches/2.2.x/   (props changed)
+    httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c
+
+Propchange: httpd/httpd/branches/2.2.x/
+------------------------------------------------------------------------------
+  Merged /httpd/httpd/trunk:r1610501
+
+Modified: httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c?rev=1611426&r1=1611425&r2=1611426&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c (original)
++++ httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c Thu Jul 17 18:20:46 2014
+@@ -37,6 +37,7 @@
+ #include "httpd.h"
+ #include "http_config.h"
+ #include "http_log.h"
++#include "http_core.h"
+ #include "apr_lib.h"
+ #include "apr_strings.h"
+ #include "apr_general.h"
+@@ -51,6 +52,9 @@
+ static const char deflateFilterName[] = "DEFLATE";
+ module AP_MODULE_DECLARE_DATA deflate_module;
+ 
++#define AP_INFLATE_RATIO_LIMIT 200
++#define AP_INFLATE_RATIO_BURST 3
++
+ typedef struct deflate_filter_config_t
+ {
+     int windowSize;
+@@ -62,6 +66,12 @@ typedef struct deflate_filter_config_t
+     char *note_output_name;
+ } deflate_filter_config;
+ 
++typedef struct deflate_dirconf_t {
++    apr_off_t inflate_limit;
++    int ratio_limit,
++        ratio_burst;
++} deflate_dirconf_t;
++
+ /* RFC 1952 Section 2.3 defines the gzip header:
+  *
+  * +---+---+---+---+---+---+---+---+---+---+
+@@ -193,6 +203,14 @@ static void *create_deflate_server_confi
+     return c;
+ }
+ 
++static void *create_deflate_dirconf(apr_pool_t *p, char *dummy)
++{
++    deflate_dirconf_t *dc = apr_pcalloc(p, sizeof(*dc));
++    dc->ratio_limit = AP_INFLATE_RATIO_LIMIT;
++    dc->ratio_burst = AP_INFLATE_RATIO_BURST;
++    return dc;
++}
++
+ static const char *deflate_set_window_size(cmd_parms *cmd, void *dummy,
+                                            const char *arg)
+ {
+@@ -284,6 +302,55 @@ static const char *deflate_set_compressi
+     return NULL;
+ }
+ 
++
++static const char *deflate_set_inflate_limit(cmd_parms *cmd, void *dirconf,
++                                      const char *arg)
++{
++    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
++    char *errp;
++
++    if (APR_SUCCESS != apr_strtoff(&dc->inflate_limit, arg, &errp, 10)) {
++        return "DeflateInflateLimitRequestBody is not parsable.";
++    }
++    if (*errp || dc->inflate_limit < 0) {
++        return "DeflateInflateLimitRequestBody requires a non-negative integer.";
++    }
++
++    return NULL;
++}
++
++static const char *deflate_set_inflate_ratio_limit(cmd_parms *cmd,
++                                                   void *dirconf,
++                                                   const char *arg)
++{
++    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
++    int i;
++
++    i = atoi(arg);
++    if (i <= 0)
++        return "DeflateInflateRatioLimit must be positive";
++
++    dc->ratio_limit = i;
++
++    return NULL;
++}
++
++static const char *deflate_set_inflate_ratio_burst(cmd_parms *cmd,
++                                                   void *dirconf,
++                                                   const char *arg)
++{
++    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
++    int i;
++
++    i = atoi(arg);
++    if (i <= 0)
++        return "DeflateInflateRatioBurst must be positive";
++
++    dc->ratio_burst = i;
++
++    return NULL;
++}
++
+ typedef struct deflate_ctx_t
+ {
+     z_stream stream;
+@@ -294,8 +361,26 @@ typedef struct deflate_ctx_t
+     unsigned char *validation_buffer;
+     apr_size_t validation_buffer_length;
+     int inflate_init;
++    int ratio_hits;
++    apr_off_t inflate_total;
+ } deflate_ctx;
+ 
++/* Check whether the (inflate) ratio exceeds the configured limit/burst. */
++static int check_ratio(request_rec *r, deflate_ctx *ctx,
++                       const deflate_dirconf_t *dc)
++{
++    if (ctx->stream.total_in) {
++        int ratio = ctx->stream.total_out / ctx->stream.total_in;
++        if (ratio < dc->ratio_limit) {
++            ctx->ratio_hits = 0;
++        }
++        else if (++ctx->ratio_hits > dc->ratio_burst) {
++            return 0;
++        }
++    }
++    return 1;
++}
++
+ /* Number of validation bytes (CRC and length) after the compressed data */
+ #define VALIDATION_SIZE 8
+ /* Do not update ctx->crc, see comment in flush_libz_buffer */
+@@ -744,6 +829,8 @@ static apr_status_t deflate_in_filter(ap
+     int zRC;
+     apr_status_t rv;
+     deflate_filter_config *c;
++    deflate_dirconf_t *dc;
++    apr_off_t inflate_limit;
+ 
+     /* just get out of the way of things we don't want. */
+     if (mode != AP_MODE_READBYTES) {
+@@ -751,6 +838,7 @@ static apr_status_t deflate_in_filter(ap
+     }
+ 
+     c = ap_get_module_config(r->server->module_config, &deflate_module);
++    dc = ap_get_module_config(r->per_dir_config, &deflate_module);
+ 
+     if (!ctx) {
+         char deflate_hdr[10];
+@@ -803,11 +891,13 @@ static apr_status_t deflate_in_filter(ap
+         if (len != 10 ||
+             deflate_hdr[0] != deflate_magic[0] ||
+             deflate_hdr[1] != deflate_magic[1]) {
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Failed to inflate input: wrong/partial magic bytes");
+             return APR_EGENERAL;
+         }
+ 
+         /* We can't handle flags for now. */
+         if (deflate_hdr[3] != 0) {
++            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Failed to inflate input: cannot handle deflate flags");
+             return APR_EGENERAL;
+         }
+ 
+@@ -831,6 +921,12 @@ static apr_status_t deflate_in_filter(ap
+         apr_brigade_cleanup(ctx->bb);
+     }
+ 
++    inflate_limit = dc->inflate_limit; 
++    if (inflate_limit == 0) { 
++        /* The core is checking the deflated body, we'll check the inflated */
++        inflate_limit = ap_get_limit_req_body(f->r);
++    }
++
+     if (APR_BRIGADE_EMPTY(ctx->proc_bb)) {
+         rv = ap_get_brigade(f->next, ctx->bb, mode, block, readbytes);
+ 
+@@ -863,6 +959,17 @@ static apr_status_t deflate_in_filter(ap
+ 
+                 ctx->stream.next_out = ctx->buffer;
+                 len = c->bufferSize - ctx->stream.avail_out;
++ 
++                ctx->inflate_total += len;
++                if (inflate_limit && ctx->inflate_total > inflate_limit) { 
++                    inflateEnd(&ctx->stream);
++                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
++                            "Inflated content length of %" APR_OFF_T_FMT
++                            " is larger than the configured limit"
++                            " of %" APR_OFF_T_FMT, 
++                            ctx->inflate_total, inflate_limit);
++                    return APR_ENOSPC;
++                }
+ 
+                 ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
+                 tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
+@@ -891,6 +998,26 @@ static apr_status_t deflate_in_filter(ap
+                     ctx->stream.next_out = ctx->buffer;
+                     len = c->bufferSize - ctx->stream.avail_out;
+ 
++                      ctx->inflate_total += len;
++                      if (inflate_limit && ctx->inflate_total > inflate_limit) { 
++                          inflateEnd(&ctx->stream);
++                          ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
++                                  "Inflated content length of %" APR_OFF_T_FMT
++                                  " is larger than the configured limit"
++                                  " of %" APR_OFF_T_FMT, 
++                                  ctx->inflate_total, inflate_limit);
++                          return APR_ENOSPC;
++                      }
++
++                      if (!check_ratio(r, ctx, dc)) {
++                          inflateEnd(&ctx->stream);
++                          ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
++                                  "Inflated content ratio is larger than the "
++                                  "configured limit %i by %i time(s)",
++                                  dc->ratio_limit, dc->ratio_burst);
++                          return APR_EINVAL;
++                      }
++
+                     ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
+                     tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
+                                                       NULL, f->c->bucket_alloc);
+@@ -1003,6 +1130,7 @@ static apr_status_t inflate_out_filter(a
+     int zRC;
+     apr_status_t rv;
+     deflate_filter_config *c;
++    deflate_dirconf_t *dc;
+ 
+     /* Do nothing if asked to filter nothing. */
+     if (APR_BRIGADE_EMPTY(bb)) {
+@@ -1010,6 +1138,7 @@ static apr_status_t inflate_out_filter(a
+     }
+ 
+     c = ap_get_module_config(r->server->module_config, &deflate_module);
++    dc = ap_get_module_config(r->per_dir_config, &deflate_module);
+ 
+     if (!ctx) {
+ 
+@@ -1272,6 +1401,14 @@ static apr_status_t inflate_out_filter(a
+         while (ctx->stream.avail_in != 0) {
+             if (ctx->stream.avail_out == 0) {
+ 
++                if (!check_ratio(r, ctx, dc)) {
++                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
++                            "Inflated content ratio is larger than the "
++                            "configured limit %i by %i time(s)",
++                            dc->ratio_limit, dc->ratio_burst);
++                    return APR_EINVAL;
++                }
++
+                 ctx->stream.next_out = ctx->buffer;
+                 len = c->bufferSize - ctx->stream.avail_out;
+ 
+@@ -1346,12 +1483,20 @@ static const command_rec deflate_filter_
+                   "Set the Deflate Memory Level (1-9)"),
+     AP_INIT_TAKE1("DeflateCompressionLevel", deflate_set_compressionlevel, NULL, RSRC_CONF,
+                   "Set the Deflate Compression Level (1-9)"),
++    AP_INIT_TAKE1("DeflateInflateLimitRequestBody", deflate_set_inflate_limit, NULL, OR_ALL,
++                  "Set a limit on size of inflated input"),
++    AP_INIT_TAKE1("DeflateInflateRatioLimit", deflate_set_inflate_ratio_limit, NULL, OR_ALL,
++                  "Set the inflate ratio limit above which inflation is "
++                  "aborted (default: " APR_STRINGIFY(AP_INFLATE_RATIO_LIMIT) ")"),
++    AP_INIT_TAKE1("DeflateInflateRatioBurst", deflate_set_inflate_ratio_burst, NULL, OR_ALL,
++                  "Set the maximum number of following inflate ratios above limit "
++                  "(default: " APR_STRINGIFY(AP_INFLATE_RATIO_BURST) ")"),
+     {NULL}
+ };
+ 
+ module AP_MODULE_DECLARE_DATA deflate_module = {
+     STANDARD20_MODULE_STUFF,
+-    NULL,                         /* dir config creater */
++    create_deflate_dirconf,       /* dir config creater */
+     NULL,                         /* dir merger --- default is to override */
+     create_deflate_server_config, /* server config */
+     NULL,                         /* merge server config */

diff --git a/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch b/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch
new file mode 100644
index 0000000..51f974e
--- /dev/null
+++ b/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch
@@ -0,0 +1,137 @@
+Author: jorton
+Date: Mon Jul 14 20:34:32 2014
+New Revision: 1610515
+
+URL: http://svn.apache.org/r1610515
+Log:
+Merge 1610491 from trunk:
+
+SECURITY (CVE-2014-0226): Fix a race condition in scoreboard handling,
+which could lead to a heap buffer overflow.  Thanks to Marek Kroemeke
+working with HP's Zero Day Initiative for reporting this.
+
+* include/scoreboard.h: Add ap_copy_scoreboard_worker.
+
+* server/scoreboard.c (ap_copy_scoreboard_worker): New function.
+
+* modules/generators/mod_status.c (status_handler): Use it.
+
+Reviewed by: trawick, jorton, covener
+Submitted by: jorton, trawick, covener
+
+Modified:
+    httpd/httpd/branches/2.2.x/   (props changed)
+    httpd/httpd/branches/2.2.x/include/ap_mmn.h
+    httpd/httpd/branches/2.2.x/include/scoreboard.h
+    httpd/httpd/branches/2.2.x/modules/generators/mod_status.c
+    httpd/httpd/branches/2.2.x/server/scoreboard.c
+
+Propchange: httpd/httpd/branches/2.2.x/
+------------------------------------------------------------------------------
+  Merged /httpd/httpd/trunk:r1610491
+
+Modified: httpd/httpd/branches/2.2.x/include/ap_mmn.h
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/ap_mmn.h?rev=1610515&r1=1610514&r2=1610515&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/include/ap_mmn.h (original)
++++ httpd/httpd/branches/2.2.x/include/ap_mmn.h Mon Jul 14 20:34:32 2014
+@@ -151,6 +151,7 @@
+  * 20051115.31 (2.2.23) Add forcerecovery to proxy_balancer_shared struct
+  * 20051115.32 (2.2.24) Add ap_get_exec_line
+  * 20051115.33 (2.2.24) Add ap_pregsub_ex()
++ * 20051115.34 (2.2.28) Add ap_copy_scoreboard_worker()
+  */
+ 
+ #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
+@@ -158,7 +159,7 @@
+ #ifndef MODULE_MAGIC_NUMBER_MAJOR
+ #define MODULE_MAGIC_NUMBER_MAJOR 20051115
+ #endif
+-#define MODULE_MAGIC_NUMBER_MINOR 33                    /* 0...n */
++#define MODULE_MAGIC_NUMBER_MINOR 34                    /* 0...n */
+ 
+ /**
+  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
+
+Modified: httpd/httpd/branches/2.2.x/include/scoreboard.h
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/scoreboard.h?rev=1610515&r1=1610514&r2=1610515&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/include/scoreboard.h (original)
++++ httpd/httpd/branches/2.2.x/include/scoreboard.h Mon Jul 14 20:34:32 2014
+@@ -189,7 +189,24 @@ AP_DECLARE(int) ap_update_child_status_f
+                                                     int status, request_rec *r);
+ void ap_time_process_request(ap_sb_handle_t *sbh, int status);
+ 
++/** Return a pointer to the worker_score for a given child, thread pair.
++ * @param child_num The child number.
++ * @param thread_num The thread number.
++ * @return A pointer to the worker_score structure.
++ * @deprecated This function is deprecated, use ap_copy_scoreboard_worker instead. 
++ */
+ AP_DECLARE(worker_score *) ap_get_scoreboard_worker(int x, int y);
++
++/** Copy the contents of a worker's scoreboard entry.  The contents of
++ * the worker_score structure are copied verbatim into the dest
++ * structure.
++ * @param dest Output parameter.
++ * @param child_num The child number.
++ * @param thread_num The thread number.
++ */
++AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest,
++                                           int child_num, int thread_num);
++
+ AP_DECLARE(process_score *) ap_get_scoreboard_process(int x);
+ AP_DECLARE(global_score *) ap_get_scoreboard_global(void);
+ AP_DECLARE(lb_score *) ap_get_scoreboard_lb(int lb_num);
+
+Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_status.c
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_status.c?rev=1610515&r1=1610514&r2=1610515&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/modules/generators/mod_status.c (original)
++++ httpd/httpd/branches/2.2.x/modules/generators/mod_status.c Mon Jul 14 20:34:32 2014
+@@ -241,7 +241,7 @@ static int status_handler(request_rec *r
+ #endif
+     int short_report;
+     int no_table_report;
+-    worker_score *ws_record;
++    worker_score *ws_record = apr_palloc(r->pool, sizeof *ws_record);
+     process_score *ps_record;
+     char *stat_buffer;
+     pid_t *pid_buffer, worker_pid;
+@@ -333,7 +333,7 @@ static int status_handler(request_rec *r
+         for (j = 0; j < thread_limit; ++j) {
+             int indx = (i * thread_limit) + j;
+ 
+-            ws_record = ap_get_scoreboard_worker(i, j);
++            ap_copy_scoreboard_worker(ws_record, i, j);
+             res = ws_record->status;
+             stat_buffer[indx] = status_flags[res];
+ 
+
+Modified: httpd/httpd/branches/2.2.x/server/scoreboard.c
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/scoreboard.c?rev=1610515&r1=1610514&r2=1610515&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/server/scoreboard.c (original)
++++ httpd/httpd/branches/2.2.x/server/scoreboard.c Mon Jul 14 20:34:32 2014
+@@ -510,6 +510,21 @@ AP_DECLARE(worker_score *) ap_get_scoreb
+     return &ap_scoreboard_image->servers[x][y];
+ }
+ 
++AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest, 
++                                           int child_num,
++                                           int thread_num)
++{
++    worker_score *ws = ap_get_scoreboard_worker(child_num, thread_num);
++
++    memcpy(dest, ws, sizeof *ws);
++
++    /* For extra safety, NUL-terminate the strings returned, though it
++     * should be true those last bytes are always zero anyway. */
++    dest->client[sizeof(dest->client) - 1] = '\0';
++    dest->request[sizeof(dest->request) - 1] = '\0';
++    dest->vhost[sizeof(dest->vhost) - 1] = '\0';
++}
++
+ AP_DECLARE(process_score *) ap_get_scoreboard_process(int x)
+ {
+     if ((x < 0) || (server_limit < x)) {

diff --git a/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch b/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch
new file mode 100644
index 0000000..e7911e0
--- /dev/null
+++ b/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch
@@ -0,0 +1,165 @@
+Author: wrowe
+Date: Wed Jul 16 20:56:51 2014
+New Revision: 1611185
+
+URL: http://svn.apache.org/r1611185
+Log:
+SECURITY: CVE-2014-0231
+
+  mod_cgid: Fix a denial of service against CGI scripts that do
+  not consume stdin that could lead to lingering HTTPD child processes
+  filling up the scoreboard and eventually hanging the server.
+
+Submitted by: Rainer Jung, Eric Covener, Yann Ylavic
+Backports: r1610509, r1535125
+Reviewed by: covener, trawick, ylavic
+
+Modified:
+    httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c
+
+Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c
+URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c?rev=1611185&r1=1611184&r2=1611185&view=diff
+==============================================================================
+--- httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c (original)
++++ httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c Wed Jul 16 20:56:51 2014
+@@ -93,6 +93,10 @@ static const char *sockname;
+ static pid_t parent_pid;
+ static ap_unix_identity_t empty_ugid = { (uid_t)-1, (gid_t)-1, -1 };
+ 
++typedef struct { 
++    apr_interval_time_t timeout;
++} cgid_dirconf;
++
+ /* The APR other-child API doesn't tell us how the daemon exited
+  * (SIGSEGV vs. exit(1)).  The other-child maintenance function
+  * needs to decide whether to restart the daemon after a failure
+@@ -934,7 +938,14 @@ static void *merge_cgid_config(apr_pool_
+     return overrides->logname ? overrides : base;
+ }
+ 
++static void *create_cgid_dirconf(apr_pool_t *p, char *dummy)
++{
++    cgid_dirconf *c = (cgid_dirconf *) apr_pcalloc(p, sizeof(cgid_dirconf));
++    return c;
++}
++
+ static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
++
+ {
+     server_rec *s = cmd->server;
+     cgid_server_conf *conf = ap_get_module_config(s->module_config,
+@@ -987,7 +998,16 @@ static const char *set_script_socket(cmd
+ 
+     return NULL;
+ }
++static const char *set_script_timeout(cmd_parms *cmd, void *dummy, const char *arg)
++{
++    cgid_dirconf *dc = dummy;
+ 
++    if (ap_timeout_parameter_parse(arg, &dc->timeout, "s") != APR_SUCCESS) { 
++        return "CGIDScriptTimeout has wrong format";
++    }
++ 
++    return NULL;
++}
+ static const command_rec cgid_cmds[] =
+ {
+     AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
+@@ -999,6 +1019,10 @@ static const command_rec cgid_cmds[] =
+     AP_INIT_TAKE1("ScriptSock", set_script_socket, NULL, RSRC_CONF,
+                   "the name of the socket to use for communication with "
+                   "the cgi daemon."),
++    AP_INIT_TAKE1("CGIDScriptTimeout", set_script_timeout, NULL, RSRC_CONF | ACCESS_CONF,
++                  "The amount of time to wait between successful reads from "
++                  "the CGI script, in seconds."),
++                  
+     {NULL}
+ };
+ 
+@@ -1335,11 +1359,15 @@ static int cgid_handler(request_rec *r)
+     apr_file_t *tempsock;
+     struct cleanup_script_info *info;
+     apr_status_t rv;
++    cgid_dirconf *dc;
+ 
+     if (strcmp(r->handler,CGI_MAGIC_TYPE) && strcmp(r->handler,"cgi-script"))
+         return DECLINED;
+ 
+     conf = ap_get_module_config(r->server->module_config, &cgid_module);
++    dc = ap_get_module_config(r->per_dir_config, &cgid_module);
++
++    
+     is_included = !strcmp(r->protocol, "INCLUDED");
+ 
+     if ((argv0 = strrchr(r->filename, '/')) != NULL)
+@@ -1412,6 +1440,12 @@ static int cgid_handler(request_rec *r)
+      */
+ 
+     apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
++    if (dc->timeout > 0) { 
++        apr_file_pipe_timeout_set(tempsock, dc->timeout);
++    }
++    else { 
++        apr_file_pipe_timeout_set(tempsock, r->server->timeout);
++    }
+     apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
+ 
+     if ((argv0 = strrchr(r->filename, '/')) != NULL)
+@@ -1487,6 +1521,10 @@ static int cgid_handler(request_rec *r)
+             if (rv != APR_SUCCESS) {
+                 /* silly script stopped reading, soak up remaining message */
+                 child_stopped_reading = 1;
++                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, 
++                              "Error writing request body to script %s", 
++                              r->filename);
++
+             }
+         }
+         apr_brigade_cleanup(bb);
+@@ -1577,7 +1615,13 @@ static int cgid_handler(request_rec *r)
+             return HTTP_MOVED_TEMPORARILY;
+         }
+ 
+-        ap_pass_brigade(r->output_filters, bb);
++        rv = ap_pass_brigade(r->output_filters, bb);
++        if (rv != APR_SUCCESS) { 
++            /* APLOG_ERR because the core output filter message is at error,
++             * but doesn't know it's passing CGI output 
++             */
++            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "Failed to flush CGI output to client");
++        }
+     }
+ 
+     if (nph) {
+@@ -1707,6 +1751,8 @@ static int include_cmd(include_ctx_t *ct
+     request_rec *r = f->r;
+     cgid_server_conf *conf = ap_get_module_config(r->server->module_config,
+                                                   &cgid_module);
++    cgid_dirconf *dc = ap_get_module_config(r->per_dir_config, &cgid_module);
++
+     struct cleanup_script_info *info;
+ 
+     add_ssi_vars(r);
+@@ -1736,6 +1782,13 @@ static int include_cmd(include_ctx_t *ct
+      * get rid of the cleanup we registered when we created the socket.
+      */
+     apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
++    if (dc->timeout > 0) {
++        apr_file_pipe_timeout_set(tempsock, dc->timeout);
++    }
++    else {
++        apr_file_pipe_timeout_set(tempsock, r->server->timeout);
++    }
++
+     apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
+ 
+     APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pipe_create(tempsock,
+@@ -1841,7 +1894,7 @@ static void register_hook(apr_pool_t *p)
+ 
+ module AP_MODULE_DECLARE_DATA cgid_module = {
+     STANDARD20_MODULE_STUFF,
+-    NULL, /* dir config creater */
++    create_cgid_dirconf, /* dir config creater */
+     NULL, /* dir merger --- default is to override */
+     create_cgid_config, /* server config */
+     merge_cgid_config, /* merge server config */

diff --git a/2.2/patches/20_all_peruser_0.4.0-rc2.patch b/2.2/patches/30_all_peruser_0.4.0-rc2.patch
similarity index 99%
rename from 2.2/patches/20_all_peruser_0.4.0-rc2.patch
rename to 2.2/patches/30_all_peruser_0.4.0-rc2.patch
index 6784c78..546d94a 100644
--- a/2.2/patches/20_all_peruser_0.4.0-rc2.patch
+++ b/2.2/patches/30_all_peruser_0.4.0-rc2.patch
@@ -30,7 +30,7 @@ diff -Nur httpd-2.2.16/modules/generators/mod_status.c httpd-2.2.16-peruser/modu
      int short_report;
      int no_table_report;
 +    int peruser_stats;
-     worker_score *ws_record;
+     worker_score *ws_record = apr_palloc(r->pool, sizeof *ws_record);
      process_score *ps_record;
      char *stat_buffer;
 @@ -268,6 +271,7 @@


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
  2014-07-31 11:29 Lars Wendler
@ 2014-08-24  9:46 ` Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2014-08-24  9:46 UTC (permalink / raw
  To: gentoo-commits

commit:     835c73fc452dfda31d782e3021959b91e56fc96a
Author:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
AuthorDate: Thu Jul 31 11:29:25 2014 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Thu Jul 31 11:29:25 2014 +0000
URL:        http://sources.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=835c73fc

Move itk patch behind peruser patch

---
 2.2/patches/{21_all-itk-20110321.patch => 31_all-itk-20110321.patch} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

diff --git a/2.2/patches/21_all-itk-20110321.patch b/2.2/patches/31_all-itk-20110321.patch
similarity index 100%
rename from 2.2/patches/21_all-itk-20110321.patch
rename to 2.2/patches/31_all-itk-20110321.patch


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [gentoo-commits] proj/apache:master commit in: 2.2/patches/
@ 2014-09-22  7:11 Lars Wendler
  0 siblings, 0 replies; 17+ messages in thread
From: Lars Wendler @ 2014-09-22  7:11 UTC (permalink / raw
  To: gentoo-commits

commit:     42a7fe0010cfeb98dcace6a1c1ec3483c11ffd29
Author:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
AuthorDate: Mon Sep 22 07:10:42 2014 +0000
Commit:     Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
CommitDate: Mon Sep 22 07:10:42 2014 +0000
URL:        http://sources.gentoo.org/gitweb/?p=proj/apache.git;a=commit;h=42a7fe00

Removed security patches which went into apache-2.2.28.

---
 2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch | 309 ------------------------
 2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch | 137 -----------
 2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch | 165 -------------
 3 files changed, 611 deletions(-)

diff --git a/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch b/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch
deleted file mode 100644
index 6db06ba..0000000
--- a/2.2/patches/26_httpd-2.2.27-CVE-2014-0118.patch
+++ /dev/null
@@ -1,309 +0,0 @@
-Author: jim
-Date: Thu Jul 17 18:20:46 2014
-New Revision: 1611426
-
-URL: http://svn.apache.org/r1611426
-Log:
-Merge r1610501 from trunk:
-
-  *) SECURITY: CVE-2014-0118 (cve.mitre.org)
-     mod_deflate: The DEFLATE input filter (inflates request bodies) now
-     limits the length and compression ratio of inflated request bodies to avoid
-     denial of sevice via highly compressed bodies.  See directives 
-     DeflateInflateLimitRequestBody, DeflateInflateRatioLimit,
-     and DeflateInflateRatioBurst.
-
-Thanks to Giancarlo Pellegrino and Davide Balzarotti for reporting the issue.
-
-Submitted By: ylavic, covener
-Reviewed By: jorton, covener, jim
-
-
-
-Submitted by: covener
-Reviewed/backported by: jim
-
-Modified:
-    httpd/httpd/branches/2.2.x/   (props changed)
-    httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c
-
-Propchange: httpd/httpd/branches/2.2.x/
-------------------------------------------------------------------------------
-  Merged /httpd/httpd/trunk:r1610501
-
-Modified: httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c
-URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c?rev=1611426&r1=1611425&r2=1611426&view=diff
-==============================================================================
---- httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c (original)
-+++ httpd/httpd/branches/2.2.x/modules/filters/mod_deflate.c Thu Jul 17 18:20:46 2014
-@@ -37,6 +37,7 @@
- #include "httpd.h"
- #include "http_config.h"
- #include "http_log.h"
-+#include "http_core.h"
- #include "apr_lib.h"
- #include "apr_strings.h"
- #include "apr_general.h"
-@@ -51,6 +52,9 @@
- static const char deflateFilterName[] = "DEFLATE";
- module AP_MODULE_DECLARE_DATA deflate_module;
- 
-+#define AP_INFLATE_RATIO_LIMIT 200
-+#define AP_INFLATE_RATIO_BURST 3
-+
- typedef struct deflate_filter_config_t
- {
-     int windowSize;
-@@ -62,6 +66,12 @@ typedef struct deflate_filter_config_t
-     char *note_output_name;
- } deflate_filter_config;
- 
-+typedef struct deflate_dirconf_t {
-+    apr_off_t inflate_limit;
-+    int ratio_limit,
-+        ratio_burst;
-+} deflate_dirconf_t;
-+
- /* RFC 1952 Section 2.3 defines the gzip header:
-  *
-  * +---+---+---+---+---+---+---+---+---+---+
-@@ -193,6 +203,14 @@ static void *create_deflate_server_confi
-     return c;
- }
- 
-+static void *create_deflate_dirconf(apr_pool_t *p, char *dummy)
-+{
-+    deflate_dirconf_t *dc = apr_pcalloc(p, sizeof(*dc));
-+    dc->ratio_limit = AP_INFLATE_RATIO_LIMIT;
-+    dc->ratio_burst = AP_INFLATE_RATIO_BURST;
-+    return dc;
-+}
-+
- static const char *deflate_set_window_size(cmd_parms *cmd, void *dummy,
-                                            const char *arg)
- {
-@@ -284,6 +302,55 @@ static const char *deflate_set_compressi
-     return NULL;
- }
- 
-+
-+static const char *deflate_set_inflate_limit(cmd_parms *cmd, void *dirconf,
-+                                      const char *arg)
-+{
-+    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
-+    char *errp;
-+
-+    if (APR_SUCCESS != apr_strtoff(&dc->inflate_limit, arg, &errp, 10)) {
-+        return "DeflateInflateLimitRequestBody is not parsable.";
-+    }
-+    if (*errp || dc->inflate_limit < 0) {
-+        return "DeflateInflateLimitRequestBody requires a non-negative integer.";
-+    }
-+
-+    return NULL;
-+}
-+
-+static const char *deflate_set_inflate_ratio_limit(cmd_parms *cmd,
-+                                                   void *dirconf,
-+                                                   const char *arg)
-+{
-+    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
-+    int i;
-+
-+    i = atoi(arg);
-+    if (i <= 0)
-+        return "DeflateInflateRatioLimit must be positive";
-+
-+    dc->ratio_limit = i;
-+
-+    return NULL;
-+}
-+
-+static const char *deflate_set_inflate_ratio_burst(cmd_parms *cmd,
-+                                                   void *dirconf,
-+                                                   const char *arg)
-+{
-+    deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
-+    int i;
-+
-+    i = atoi(arg);
-+    if (i <= 0)
-+        return "DeflateInflateRatioBurst must be positive";
-+
-+    dc->ratio_burst = i;
-+
-+    return NULL;
-+}
-+
- typedef struct deflate_ctx_t
- {
-     z_stream stream;
-@@ -294,8 +361,26 @@ typedef struct deflate_ctx_t
-     unsigned char *validation_buffer;
-     apr_size_t validation_buffer_length;
-     int inflate_init;
-+    int ratio_hits;
-+    apr_off_t inflate_total;
- } deflate_ctx;
- 
-+/* Check whether the (inflate) ratio exceeds the configured limit/burst. */
-+static int check_ratio(request_rec *r, deflate_ctx *ctx,
-+                       const deflate_dirconf_t *dc)
-+{
-+    if (ctx->stream.total_in) {
-+        int ratio = ctx->stream.total_out / ctx->stream.total_in;
-+        if (ratio < dc->ratio_limit) {
-+            ctx->ratio_hits = 0;
-+        }
-+        else if (++ctx->ratio_hits > dc->ratio_burst) {
-+            return 0;
-+        }
-+    }
-+    return 1;
-+}
-+
- /* Number of validation bytes (CRC and length) after the compressed data */
- #define VALIDATION_SIZE 8
- /* Do not update ctx->crc, see comment in flush_libz_buffer */
-@@ -744,6 +829,8 @@ static apr_status_t deflate_in_filter(ap
-     int zRC;
-     apr_status_t rv;
-     deflate_filter_config *c;
-+    deflate_dirconf_t *dc;
-+    apr_off_t inflate_limit;
- 
-     /* just get out of the way of things we don't want. */
-     if (mode != AP_MODE_READBYTES) {
-@@ -751,6 +838,7 @@ static apr_status_t deflate_in_filter(ap
-     }
- 
-     c = ap_get_module_config(r->server->module_config, &deflate_module);
-+    dc = ap_get_module_config(r->per_dir_config, &deflate_module);
- 
-     if (!ctx) {
-         char deflate_hdr[10];
-@@ -803,11 +891,13 @@ static apr_status_t deflate_in_filter(ap
-         if (len != 10 ||
-             deflate_hdr[0] != deflate_magic[0] ||
-             deflate_hdr[1] != deflate_magic[1]) {
-+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Failed to inflate input: wrong/partial magic bytes");
-             return APR_EGENERAL;
-         }
- 
-         /* We can't handle flags for now. */
-         if (deflate_hdr[3] != 0) {
-+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Failed to inflate input: cannot handle deflate flags");
-             return APR_EGENERAL;
-         }
- 
-@@ -831,6 +921,12 @@ static apr_status_t deflate_in_filter(ap
-         apr_brigade_cleanup(ctx->bb);
-     }
- 
-+    inflate_limit = dc->inflate_limit; 
-+    if (inflate_limit == 0) { 
-+        /* The core is checking the deflated body, we'll check the inflated */
-+        inflate_limit = ap_get_limit_req_body(f->r);
-+    }
-+
-     if (APR_BRIGADE_EMPTY(ctx->proc_bb)) {
-         rv = ap_get_brigade(f->next, ctx->bb, mode, block, readbytes);
- 
-@@ -863,6 +959,17 @@ static apr_status_t deflate_in_filter(ap
- 
-                 ctx->stream.next_out = ctx->buffer;
-                 len = c->bufferSize - ctx->stream.avail_out;
-+ 
-+                ctx->inflate_total += len;
-+                if (inflate_limit && ctx->inflate_total > inflate_limit) { 
-+                    inflateEnd(&ctx->stream);
-+                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
-+                            "Inflated content length of %" APR_OFF_T_FMT
-+                            " is larger than the configured limit"
-+                            " of %" APR_OFF_T_FMT, 
-+                            ctx->inflate_total, inflate_limit);
-+                    return APR_ENOSPC;
-+                }
- 
-                 ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
-                 tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
-@@ -891,6 +998,26 @@ static apr_status_t deflate_in_filter(ap
-                     ctx->stream.next_out = ctx->buffer;
-                     len = c->bufferSize - ctx->stream.avail_out;
- 
-+                      ctx->inflate_total += len;
-+                      if (inflate_limit && ctx->inflate_total > inflate_limit) { 
-+                          inflateEnd(&ctx->stream);
-+                          ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
-+                                  "Inflated content length of %" APR_OFF_T_FMT
-+                                  " is larger than the configured limit"
-+                                  " of %" APR_OFF_T_FMT, 
-+                                  ctx->inflate_total, inflate_limit);
-+                          return APR_ENOSPC;
-+                      }
-+
-+                      if (!check_ratio(r, ctx, dc)) {
-+                          inflateEnd(&ctx->stream);
-+                          ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
-+                                  "Inflated content ratio is larger than the "
-+                                  "configured limit %i by %i time(s)",
-+                                  dc->ratio_limit, dc->ratio_burst);
-+                          return APR_EINVAL;
-+                      }
-+
-                     ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
-                     tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
-                                                       NULL, f->c->bucket_alloc);
-@@ -1003,6 +1130,7 @@ static apr_status_t inflate_out_filter(a
-     int zRC;
-     apr_status_t rv;
-     deflate_filter_config *c;
-+    deflate_dirconf_t *dc;
- 
-     /* Do nothing if asked to filter nothing. */
-     if (APR_BRIGADE_EMPTY(bb)) {
-@@ -1010,6 +1138,7 @@ static apr_status_t inflate_out_filter(a
-     }
- 
-     c = ap_get_module_config(r->server->module_config, &deflate_module);
-+    dc = ap_get_module_config(r->per_dir_config, &deflate_module);
- 
-     if (!ctx) {
- 
-@@ -1272,6 +1401,14 @@ static apr_status_t inflate_out_filter(a
-         while (ctx->stream.avail_in != 0) {
-             if (ctx->stream.avail_out == 0) {
- 
-+                if (!check_ratio(r, ctx, dc)) {
-+                    ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, 
-+                            "Inflated content ratio is larger than the "
-+                            "configured limit %i by %i time(s)",
-+                            dc->ratio_limit, dc->ratio_burst);
-+                    return APR_EINVAL;
-+                }
-+
-                 ctx->stream.next_out = ctx->buffer;
-                 len = c->bufferSize - ctx->stream.avail_out;
- 
-@@ -1346,12 +1483,20 @@ static const command_rec deflate_filter_
-                   "Set the Deflate Memory Level (1-9)"),
-     AP_INIT_TAKE1("DeflateCompressionLevel", deflate_set_compressionlevel, NULL, RSRC_CONF,
-                   "Set the Deflate Compression Level (1-9)"),
-+    AP_INIT_TAKE1("DeflateInflateLimitRequestBody", deflate_set_inflate_limit, NULL, OR_ALL,
-+                  "Set a limit on size of inflated input"),
-+    AP_INIT_TAKE1("DeflateInflateRatioLimit", deflate_set_inflate_ratio_limit, NULL, OR_ALL,
-+                  "Set the inflate ratio limit above which inflation is "
-+                  "aborted (default: " APR_STRINGIFY(AP_INFLATE_RATIO_LIMIT) ")"),
-+    AP_INIT_TAKE1("DeflateInflateRatioBurst", deflate_set_inflate_ratio_burst, NULL, OR_ALL,
-+                  "Set the maximum number of following inflate ratios above limit "
-+                  "(default: " APR_STRINGIFY(AP_INFLATE_RATIO_BURST) ")"),
-     {NULL}
- };
- 
- module AP_MODULE_DECLARE_DATA deflate_module = {
-     STANDARD20_MODULE_STUFF,
--    NULL,                         /* dir config creater */
-+    create_deflate_dirconf,       /* dir config creater */
-     NULL,                         /* dir merger --- default is to override */
-     create_deflate_server_config, /* server config */
-     NULL,                         /* merge server config */

diff --git a/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch b/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch
deleted file mode 100644
index 51f974e..0000000
--- a/2.2/patches/27_httpd-2.2.27-CVE-2014-0226.patch
+++ /dev/null
@@ -1,137 +0,0 @@
-Author: jorton
-Date: Mon Jul 14 20:34:32 2014
-New Revision: 1610515
-
-URL: http://svn.apache.org/r1610515
-Log:
-Merge 1610491 from trunk:
-
-SECURITY (CVE-2014-0226): Fix a race condition in scoreboard handling,
-which could lead to a heap buffer overflow.  Thanks to Marek Kroemeke
-working with HP's Zero Day Initiative for reporting this.
-
-* include/scoreboard.h: Add ap_copy_scoreboard_worker.
-
-* server/scoreboard.c (ap_copy_scoreboard_worker): New function.
-
-* modules/generators/mod_status.c (status_handler): Use it.
-
-Reviewed by: trawick, jorton, covener
-Submitted by: jorton, trawick, covener
-
-Modified:
-    httpd/httpd/branches/2.2.x/   (props changed)
-    httpd/httpd/branches/2.2.x/include/ap_mmn.h
-    httpd/httpd/branches/2.2.x/include/scoreboard.h
-    httpd/httpd/branches/2.2.x/modules/generators/mod_status.c
-    httpd/httpd/branches/2.2.x/server/scoreboard.c
-
-Propchange: httpd/httpd/branches/2.2.x/
-------------------------------------------------------------------------------
-  Merged /httpd/httpd/trunk:r1610491
-
-Modified: httpd/httpd/branches/2.2.x/include/ap_mmn.h
-URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/ap_mmn.h?rev=1610515&r1=1610514&r2=1610515&view=diff
-==============================================================================
---- httpd/httpd/branches/2.2.x/include/ap_mmn.h (original)
-+++ httpd/httpd/branches/2.2.x/include/ap_mmn.h Mon Jul 14 20:34:32 2014
-@@ -151,6 +151,7 @@
-  * 20051115.31 (2.2.23) Add forcerecovery to proxy_balancer_shared struct
-  * 20051115.32 (2.2.24) Add ap_get_exec_line
-  * 20051115.33 (2.2.24) Add ap_pregsub_ex()
-+ * 20051115.34 (2.2.28) Add ap_copy_scoreboard_worker()
-  */
- 
- #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
-@@ -158,7 +159,7 @@
- #ifndef MODULE_MAGIC_NUMBER_MAJOR
- #define MODULE_MAGIC_NUMBER_MAJOR 20051115
- #endif
--#define MODULE_MAGIC_NUMBER_MINOR 33                    /* 0...n */
-+#define MODULE_MAGIC_NUMBER_MINOR 34                    /* 0...n */
- 
- /**
-  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
-
-Modified: httpd/httpd/branches/2.2.x/include/scoreboard.h
-URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/include/scoreboard.h?rev=1610515&r1=1610514&r2=1610515&view=diff
-==============================================================================
---- httpd/httpd/branches/2.2.x/include/scoreboard.h (original)
-+++ httpd/httpd/branches/2.2.x/include/scoreboard.h Mon Jul 14 20:34:32 2014
-@@ -189,7 +189,24 @@ AP_DECLARE(int) ap_update_child_status_f
-                                                     int status, request_rec *r);
- void ap_time_process_request(ap_sb_handle_t *sbh, int status);
- 
-+/** Return a pointer to the worker_score for a given child, thread pair.
-+ * @param child_num The child number.
-+ * @param thread_num The thread number.
-+ * @return A pointer to the worker_score structure.
-+ * @deprecated This function is deprecated, use ap_copy_scoreboard_worker instead. 
-+ */
- AP_DECLARE(worker_score *) ap_get_scoreboard_worker(int x, int y);
-+
-+/** Copy the contents of a worker's scoreboard entry.  The contents of
-+ * the worker_score structure are copied verbatim into the dest
-+ * structure.
-+ * @param dest Output parameter.
-+ * @param child_num The child number.
-+ * @param thread_num The thread number.
-+ */
-+AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest,
-+                                           int child_num, int thread_num);
-+
- AP_DECLARE(process_score *) ap_get_scoreboard_process(int x);
- AP_DECLARE(global_score *) ap_get_scoreboard_global(void);
- AP_DECLARE(lb_score *) ap_get_scoreboard_lb(int lb_num);
-
-Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_status.c
-URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_status.c?rev=1610515&r1=1610514&r2=1610515&view=diff
-==============================================================================
---- httpd/httpd/branches/2.2.x/modules/generators/mod_status.c (original)
-+++ httpd/httpd/branches/2.2.x/modules/generators/mod_status.c Mon Jul 14 20:34:32 2014
-@@ -241,7 +241,7 @@ static int status_handler(request_rec *r
- #endif
-     int short_report;
-     int no_table_report;
--    worker_score *ws_record;
-+    worker_score *ws_record = apr_palloc(r->pool, sizeof *ws_record);
-     process_score *ps_record;
-     char *stat_buffer;
-     pid_t *pid_buffer, worker_pid;
-@@ -333,7 +333,7 @@ static int status_handler(request_rec *r
-         for (j = 0; j < thread_limit; ++j) {
-             int indx = (i * thread_limit) + j;
- 
--            ws_record = ap_get_scoreboard_worker(i, j);
-+            ap_copy_scoreboard_worker(ws_record, i, j);
-             res = ws_record->status;
-             stat_buffer[indx] = status_flags[res];
- 
-
-Modified: httpd/httpd/branches/2.2.x/server/scoreboard.c
-URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/server/scoreboard.c?rev=1610515&r1=1610514&r2=1610515&view=diff
-==============================================================================
---- httpd/httpd/branches/2.2.x/server/scoreboard.c (original)
-+++ httpd/httpd/branches/2.2.x/server/scoreboard.c Mon Jul 14 20:34:32 2014
-@@ -510,6 +510,21 @@ AP_DECLARE(worker_score *) ap_get_scoreb
-     return &ap_scoreboard_image->servers[x][y];
- }
- 
-+AP_DECLARE(void) ap_copy_scoreboard_worker(worker_score *dest, 
-+                                           int child_num,
-+                                           int thread_num)
-+{
-+    worker_score *ws = ap_get_scoreboard_worker(child_num, thread_num);
-+
-+    memcpy(dest, ws, sizeof *ws);
-+
-+    /* For extra safety, NUL-terminate the strings returned, though it
-+     * should be true those last bytes are always zero anyway. */
-+    dest->client[sizeof(dest->client) - 1] = '\0';
-+    dest->request[sizeof(dest->request) - 1] = '\0';
-+    dest->vhost[sizeof(dest->vhost) - 1] = '\0';
-+}
-+
- AP_DECLARE(process_score *) ap_get_scoreboard_process(int x)
- {
-     if ((x < 0) || (server_limit < x)) {

diff --git a/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch b/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch
deleted file mode 100644
index e7911e0..0000000
--- a/2.2/patches/28_httpd-2.2.27-CVE-2014-0231.patch
+++ /dev/null
@@ -1,165 +0,0 @@
-Author: wrowe
-Date: Wed Jul 16 20:56:51 2014
-New Revision: 1611185
-
-URL: http://svn.apache.org/r1611185
-Log:
-SECURITY: CVE-2014-0231
-
-  mod_cgid: Fix a denial of service against CGI scripts that do
-  not consume stdin that could lead to lingering HTTPD child processes
-  filling up the scoreboard and eventually hanging the server.
-
-Submitted by: Rainer Jung, Eric Covener, Yann Ylavic
-Backports: r1610509, r1535125
-Reviewed by: covener, trawick, ylavic
-
-Modified:
-    httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c
-
-Modified: httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c
-URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c?rev=1611185&r1=1611184&r2=1611185&view=diff
-==============================================================================
---- httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c (original)
-+++ httpd/httpd/branches/2.2.x/modules/generators/mod_cgid.c Wed Jul 16 20:56:51 2014
-@@ -93,6 +93,10 @@ static const char *sockname;
- static pid_t parent_pid;
- static ap_unix_identity_t empty_ugid = { (uid_t)-1, (gid_t)-1, -1 };
- 
-+typedef struct { 
-+    apr_interval_time_t timeout;
-+} cgid_dirconf;
-+
- /* The APR other-child API doesn't tell us how the daemon exited
-  * (SIGSEGV vs. exit(1)).  The other-child maintenance function
-  * needs to decide whether to restart the daemon after a failure
-@@ -934,7 +938,14 @@ static void *merge_cgid_config(apr_pool_
-     return overrides->logname ? overrides : base;
- }
- 
-+static void *create_cgid_dirconf(apr_pool_t *p, char *dummy)
-+{
-+    cgid_dirconf *c = (cgid_dirconf *) apr_pcalloc(p, sizeof(cgid_dirconf));
-+    return c;
-+}
-+
- static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
-+
- {
-     server_rec *s = cmd->server;
-     cgid_server_conf *conf = ap_get_module_config(s->module_config,
-@@ -987,7 +998,16 @@ static const char *set_script_socket(cmd
- 
-     return NULL;
- }
-+static const char *set_script_timeout(cmd_parms *cmd, void *dummy, const char *arg)
-+{
-+    cgid_dirconf *dc = dummy;
- 
-+    if (ap_timeout_parameter_parse(arg, &dc->timeout, "s") != APR_SUCCESS) { 
-+        return "CGIDScriptTimeout has wrong format";
-+    }
-+ 
-+    return NULL;
-+}
- static const command_rec cgid_cmds[] =
- {
-     AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
-@@ -999,6 +1019,10 @@ static const command_rec cgid_cmds[] =
-     AP_INIT_TAKE1("ScriptSock", set_script_socket, NULL, RSRC_CONF,
-                   "the name of the socket to use for communication with "
-                   "the cgi daemon."),
-+    AP_INIT_TAKE1("CGIDScriptTimeout", set_script_timeout, NULL, RSRC_CONF | ACCESS_CONF,
-+                  "The amount of time to wait between successful reads from "
-+                  "the CGI script, in seconds."),
-+                  
-     {NULL}
- };
- 
-@@ -1335,11 +1359,15 @@ static int cgid_handler(request_rec *r)
-     apr_file_t *tempsock;
-     struct cleanup_script_info *info;
-     apr_status_t rv;
-+    cgid_dirconf *dc;
- 
-     if (strcmp(r->handler,CGI_MAGIC_TYPE) && strcmp(r->handler,"cgi-script"))
-         return DECLINED;
- 
-     conf = ap_get_module_config(r->server->module_config, &cgid_module);
-+    dc = ap_get_module_config(r->per_dir_config, &cgid_module);
-+
-+    
-     is_included = !strcmp(r->protocol, "INCLUDED");
- 
-     if ((argv0 = strrchr(r->filename, '/')) != NULL)
-@@ -1412,6 +1440,12 @@ static int cgid_handler(request_rec *r)
-      */
- 
-     apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
-+    if (dc->timeout > 0) { 
-+        apr_file_pipe_timeout_set(tempsock, dc->timeout);
-+    }
-+    else { 
-+        apr_file_pipe_timeout_set(tempsock, r->server->timeout);
-+    }
-     apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
- 
-     if ((argv0 = strrchr(r->filename, '/')) != NULL)
-@@ -1487,6 +1521,10 @@ static int cgid_handler(request_rec *r)
-             if (rv != APR_SUCCESS) {
-                 /* silly script stopped reading, soak up remaining message */
-                 child_stopped_reading = 1;
-+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, 
-+                              "Error writing request body to script %s", 
-+                              r->filename);
-+
-             }
-         }
-         apr_brigade_cleanup(bb);
-@@ -1577,7 +1615,13 @@ static int cgid_handler(request_rec *r)
-             return HTTP_MOVED_TEMPORARILY;
-         }
- 
--        ap_pass_brigade(r->output_filters, bb);
-+        rv = ap_pass_brigade(r->output_filters, bb);
-+        if (rv != APR_SUCCESS) { 
-+            /* APLOG_ERR because the core output filter message is at error,
-+             * but doesn't know it's passing CGI output 
-+             */
-+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "Failed to flush CGI output to client");
-+        }
-     }
- 
-     if (nph) {
-@@ -1707,6 +1751,8 @@ static int include_cmd(include_ctx_t *ct
-     request_rec *r = f->r;
-     cgid_server_conf *conf = ap_get_module_config(r->server->module_config,
-                                                   &cgid_module);
-+    cgid_dirconf *dc = ap_get_module_config(r->per_dir_config, &cgid_module);
-+
-     struct cleanup_script_info *info;
- 
-     add_ssi_vars(r);
-@@ -1736,6 +1782,13 @@ static int include_cmd(include_ctx_t *ct
-      * get rid of the cleanup we registered when we created the socket.
-      */
-     apr_os_pipe_put_ex(&tempsock, &sd, 1, r->pool);
-+    if (dc->timeout > 0) {
-+        apr_file_pipe_timeout_set(tempsock, dc->timeout);
-+    }
-+    else {
-+        apr_file_pipe_timeout_set(tempsock, r->server->timeout);
-+    }
-+
-     apr_pool_cleanup_kill(r->pool, (void *)((long)sd), close_unix_socket);
- 
-     APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pipe_create(tempsock,
-@@ -1841,7 +1894,7 @@ static void register_hook(apr_pool_t *p)
- 
- module AP_MODULE_DECLARE_DATA cgid_module = {
-     STANDARD20_MODULE_STUFF,
--    NULL, /* dir config creater */
-+    create_cgid_dirconf, /* dir config creater */
-     NULL, /* dir merger --- default is to override */
-     create_cgid_config, /* server config */
-     merge_cgid_config, /* merge server config */


^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2014-09-22  7:11 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-09 15:33 [gentoo-commits] proj/apache:master commit in: 2.2/patches/ Lars Wendler
  -- strict thread matches above, loose matches on Subject: below --
2014-09-22  7:11 Lars Wendler
2014-07-31 11:29 Lars Wendler
2014-08-24  9:46 ` Lars Wendler
2014-07-31 11:25 Lars Wendler
2014-08-24  9:46 ` Lars Wendler
2013-11-09 21:23 Lars Wendler
2013-11-09 15:33 Lars Wendler
2013-11-09 15:33 Lars Wendler
2013-11-09 15:33 Lars Wendler
2013-11-09 15:33 Lars Wendler
2013-11-09 15:32 Lars Wendler
2013-11-09 15:32 Lars Wendler
2013-11-09 15:32 Lars Wendler
2013-11-09 15:32 Lars Wendler
2013-11-09 15:32 Lars Wendler
2013-11-09 15:32 Lars Wendler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox