PR-6223104-ulimit.diff   [plain text]


--- docs/conf/extra/httpd-mpm.conf.in.orig	2010-10-28 15:17:47.000000000 -0500
+++ docs/conf/extra/httpd-mpm.conf.in	2010-11-01 16:15:08.000000000 -0500
@@ -33,11 +33,16 @@
 # MaxSpareServers: maximum number of server processes which are kept spare
 # MaxClients: maximum number of server processes allowed to start
 # MaxRequestsPerChild: maximum number of requests a server process serves
+# ServerLimit and MaxClients support n% syntax which sets them to a
+# fraction of the current RLIMIT_NPROC limit.  On error the values
+# are unchanged, so set a numeric value first just in case.
 <IfModule mpm_prefork_module>
     StartServers          1
     MinSpareServers       1
     MaxSpareServers      10
+    ServerLimit          50%
     MaxClients          150
+    MaxClients           50%
     MaxRequestsPerChild   0
 </IfModule>
 
--- server/mpm/prefork/prefork.c.orig	2010-10-11 23:21:28.000000000 -0500
+++ server/mpm/prefork/prefork.c	2010-11-01 16:13:10.000000000 -0500
@@ -1412,14 +1412,42 @@
     return NULL;
 }
 
+#include <sys/resource.h>
+static int getproclimit(void)
+{
+    struct rlimit rl;
+    memset(&rl, 0, sizeof rl);
+    return getrlimit(RLIMIT_NPROC, &rl) == 0 ? rl.rlim_cur : 0;
+}
+
 static const char *set_max_clients (cmd_parms *cmd, void *dummy, const char *arg)
 {
+    int tmp_daemons_limit;
+
     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
     if (err != NULL) {
         return err;
     }
 
-    ap_daemons_limit = atoi(arg);
+    tmp_daemons_limit = atoi(arg);
+    if (strlen(arg) > 0 && arg[strlen(arg) - 1] == '%') {
+	int proclimit = getproclimit();
+	if (proclimit <= 0) {
+	    ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+			 "WARNING: MaxClients %d%% ignored because "
+			 "RLIMIT_NPROC is unknown", tmp_daemons_limit);
+	    return NULL;
+	}
+	if (tmp_daemons_limit < 1 || tmp_daemons_limit > 100) {
+	    ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+			 "WARNING: MaxClients %d%% ignored because "
+			 "percentage is out of range 1-100%%",
+			 tmp_daemons_limit);
+	    return NULL;
+	}
+	tmp_daemons_limit = proclimit * tmp_daemons_limit / 100.0 + 0.5;
+    }
+    ap_daemons_limit = tmp_daemons_limit;
     if (ap_daemons_limit > server_limit) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
                     "WARNING: MaxClients of %d exceeds ServerLimit value "
@@ -1449,6 +1477,23 @@
     }
 
     tmp_server_limit = atoi(arg);
+    if (strlen(arg) > 0 && arg[strlen(arg) - 1] == '%') {
+	int proclimit = getproclimit();
+	if (proclimit <= 0) {
+	    ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+			 "WARNING: ServerLimit %d%% ignored because "
+			 "RLIMIT_NPROC is unknown", tmp_server_limit);
+	    return NULL;
+	}
+	if (tmp_server_limit < 1 || tmp_server_limit > 100) {
+	    ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+			 "WARNING: ServerLimit %d%% ignored because "
+			 "percentage is out of range 1-100%%",
+			 tmp_server_limit);
+	    return NULL;
+	}
+	tmp_server_limit = proclimit * tmp_server_limit / 100.0 + 0.5;
+    }
     /* you cannot change ServerLimit across a restart; ignore
      * any such attempts
      */