--- mod_suphp.orig.c	2013-07-03 08:38:58.000000000 -0500
+++ mod_suphp.c	2013-10-28 08:16:26.323791052 -0500
@@ -124,6 +124,8 @@
 #endif
     apr_table_t *handlers;
     char *php_path;
+    char *nproc;
+    char *nproc_err;
 } suphp_conf;
 
 
@@ -199,7 +201,9 @@
     cfg->engine = SUPHP_ENGINE_UNDEFINED;
     cfg->php_path = NULL;
     cfg->cmode = SUPHP_CONFIG_MODE_SERVER;
-    
+    cfg->nproc = NULL;
+    cfg->nproc_err = NULL;
+
     /* Create table with 0 initial elements */
     /* This size may be increased for performance reasons */
     cfg->handlers = apr_table_make(p, 0);
@@ -219,6 +223,20 @@
         merged->engine = child->engine;
     else
         merged->engine = parent->engine;
+
+    if (child->nproc)
+        merged->nproc = apr_pstrdup(p, child->nproc);
+    else if (parent->nproc)
+        merged->nproc = apr_pstrdup(p, parent->nproc);
+    else
+        merged->nproc = NULL;
+
+    if (child->nproc_err)
+        merged->nproc_err = apr_pstrdup(p, child->nproc_err);
+    else if (parent->nproc_err)
+        merged->nproc_err = apr_pstrdup(p, parent->nproc_err);
+    else
+        merged->nproc_err = NULL;
     
     if (child->php_path != NULL)
         merged->php_path = apr_pstrdup(p, child->php_path);
@@ -335,6 +353,32 @@
 }
 
 
+static const char *suphp_handle_cmd_nproc(cmd_parms *cmd, void* mconfig, const char *arg)
+{
+    server_rec *s = cmd->server;
+    suphp_conf *cfg;
+    
+    cfg = (suphp_conf *) ap_get_module_config(s->module_config, &suphp_module);
+    
+    cfg->nproc = apr_pstrdup(cmd->pool, arg);
+    
+    return NULL;
+}
+
+
+static const char *suphp_handle_cmd_nproc_err(cmd_parms *cmd, void* mconfig, const char *arg)
+{
+    server_rec *s = cmd->server;
+    suphp_conf *cfg;
+    
+    cfg = (suphp_conf *) ap_get_module_config(s->module_config, &suphp_module);
+    
+    cfg->nproc_err = apr_pstrdup(cmd->pool, arg);
+    
+    return NULL;
+}
+
+
 static const char *suphp_handle_cmd_phppath(cmd_parms *cmd, void* mconfig, const char *arg)
 {
     server_rec *s = cmd->server;
@@ -354,6 +398,10 @@
                  "Whether suPHP is on or off, default is off"),
     AP_INIT_TAKE1("suPHP_ConfigPath", suphp_handle_cmd_config, NULL, OR_OPTIONS,
                   "Wheres the php.ini resides, default is the PHP default"),
+    AP_INIT_TAKE1("suPHP_NProc", suphp_handle_cmd_nproc, NULL, RSRC_CONF,
+                  "Maximum number of permitted PHP processes"),
+    AP_INIT_TAKE1("suPHP_NProcError", suphp_handle_cmd_nproc_err, NULL, RSRC_CONF,
+                  "Error code to return once maximum number of permitted PHP processes has been reached"),
 #ifdef SUPHP_USE_USERGROUP
     AP_INIT_TAKE2("suPHP_UserGroup", suphp_handle_cmd_user_group, NULL, RSRC_CONF | ACCESS_CONF,
                   "User and group scripts shall be run as"),
@@ -760,7 +808,8 @@
     int ud_success = 0;
     ap_unix_identity_t *userdir_id = NULL;
 #endif
-    
+
+    struct rlimit reslim;
     apr_bucket_brigade *bb;
     apr_bucket *b;
     
@@ -770,7 +819,17 @@
     sconf = ap_get_module_config(r->server->module_config, &suphp_module);
     dconf = ap_get_module_config(r->per_dir_config, &suphp_module);
     core_conf = (core_dir_config *) ap_get_module_config(r->per_dir_config, &core_module);
-    
+
+    if (sconf->nproc) {
+        reslim.rlim_cur = atoi(sconf->nproc);
+        reslim.rlim_max = atoi(sconf->nproc);
+    } else {
+        reslim.rlim_cur = 500000;
+        reslim.rlim_max = 500000;
+    }
+
+    /* ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Limiting processes to %s", sconf->nproc); */
+
     /* check if suPHP is enabled for this request */
     
     if (((sconf->engine != SUPHP_ENGINE_ON)
@@ -923,23 +982,24 @@
     env = ap_create_environment(p, r->subprocess_env);
         
     /* set attributes for new process */
-    
+
     if (((rv = apr_procattr_create(&procattr, p)) != APR_SUCCESS)
         || ((rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK)) != APR_SUCCESS)
         || ((rv = apr_procattr_dir_set(procattr, ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS)
     
     /* set resource limits */
-
 #ifdef RLIMIT_CPU
         || ((rv = apr_procattr_limit_set(procattr, APR_LIMIT_CPU, core_conf->limit_cpu)) != APR_SUCCESS)
 #endif
 #if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
         || ((rv = apr_procattr_limit_set(procattr, APR_LIMIT_MEM, core_conf->limit_mem)) != APR_SUCCESS)
 #endif
+/* This causes Apache's RLimitNProc to not be used.
 #ifdef RLIMIT_NPROC
         || ((apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, core_conf->limit_nproc)) != APR_SUCCESS)
 #endif
-
+*/
+        || ((apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, &reslim)) != APR_SUCCESS)
         || ((apr_procattr_cmdtype_set(procattr, APR_PROGRAM)) != APR_SUCCESS)
         || ((apr_procattr_error_check_set(procattr, 1)) != APR_SUCCESS)
         || ((apr_procattr_detach_set(procattr, 0)) != APR_SUCCESS))
@@ -1060,8 +1120,16 @@
             
             /* ap_scan_script_header_err_brigade does logging itself,
                so simply return                                       */
-               
-            return HTTP_INTERNAL_SERVER_ERROR;
+            if (sconf->nproc_err) {
+                    if (sconf->nproc && sconf->target_user) {
+                         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "suPHP process limit (%s) has been reached for %s", sconf->nproc, sconf->target_user);
+                    } else if (sconf->nproc && dconf->target_user) {
+                         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "suPHP process limit (%s) has been reached for %s", sconf->nproc, dconf->target_user);
+                    }
+	            return atoi(sconf->nproc_err);
+            } else {
+                    return HTTP_INTERNAL_SERVER_ERROR;
+            }
         }
         
         location = apr_table_get(r->headers_out, "Location");
