A certain person complained over the phone again this a.m. about
having to tweak HARD_SERVER_LIMIT define for daedalus, and prefork MPM
is a simpler playground than worker for figuring out the user
interface (since there is no HARD_THREAD_LIMIT), so what the heck...

This adds a HardServerLimit directive to prefork which allows you to
set a really big* limit on MaxClients (if you can spare the shared
memory).  As always, you get to play with MaxClients across restarts
but you can't play with HardServerLimit.

*what is really big?  the admin should know what they're doing, but
just to catch obvious errors I put a limit of 20,000 on the value; if
that causes anybody problems I'd like an account on that machine :)
maybe we need to come up with a better magic number (99,999?)

We catch (and ignore) attempts to change HardServerLimit across
restarts, but for the life of me I don't know how to log an error in
that scenario.  Log messages during restart config processing seem to
go to the bit bucket.

I could squirrel away the message and drop it in the log once I get to
ap_mpm_run() but that's pretty gross :(

I would not recommend putting HardServerLimit in the standard
configuration file.  We should have a default HardServerLimit that
works for most folks, and the remaining few will get a warning
messages at startup telling them to look at the HardServerLimit
directive.

Index: server/mpm/prefork/prefork.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/prefork/prefork.c,v
retrieving revision 1.225
diff -u -r1.225 prefork.c
--- server/mpm/prefork/prefork.c        2001/12/18 13:48:53     1.225
+++ server/mpm/prefork/prefork.c        2001/12/18 16:08:58
@@ -114,10 +114,17 @@
  * enough that we can read the whole thing without worrying too much about
  * the overhead.
  */
-#ifndef HARD_SERVER_LIMIT
-#define HARD_SERVER_LIMIT 256
+#ifndef DEFAULT_HARD_SERVER_LIMIT
+#define DEFAULT_HARD_SERVER_LIMIT 256
 #endif
 
+/* Admin can't tune HardServerLimit beyond HARD_SERVER_MAX.  We want
+ * some sort of compile-time limit to help catch typos.
+ */
+#ifndef MAX_HARD_SERVER_LIMIT
+#define MAX_HARD_SERVER_LIMIT 20000
+#endif
+
 #ifndef HARD_THREAD_LIMIT
 #define HARD_THREAD_LIMIT 1
 #endif
@@ -129,7 +136,9 @@
 static int ap_daemons_to_start=0;
 static int ap_daemons_min_free=0;
 static int ap_daemons_max_free=0;
-static int ap_daemons_limit=0;
+static int ap_daemons_limit=0;      /* MaxClients */
+static int hard_server_limit = DEFAULT_HARD_SERVER_LIMIT;
+static int first_hard_server_limit;
 
 static ap_pod_t *pod;
 
@@ -319,7 +328,7 @@
             *result = AP_MPMQ_DYNAMIC;
             return APR_SUCCESS;
         case AP_MPMQ_HARD_LIMIT_DAEMONS:
-            *result = HARD_SERVER_LIMIT;
+            *result = hard_server_limit;
             return APR_SUCCESS;
         case AP_MPMQ_HARD_LIMIT_THREADS:
             *result = HARD_THREAD_LIMIT;
@@ -966,7 +975,9 @@
     pconf = _pconf;
 
     ap_server_conf = s;
- 
+
+    first_hard_server_limit = hard_server_limit;
+
     if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) {
        /* XXX: hey, what's the right way for the mpm to indicate a fatal error? */
         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, 0, s,
@@ -1212,7 +1223,7 @@
     ap_daemons_to_start = DEFAULT_START_DAEMON;
     ap_daemons_min_free = DEFAULT_MIN_FREE_DAEMON;
     ap_daemons_max_free = DEFAULT_MAX_FREE_DAEMON;
-    ap_daemons_limit = HARD_SERVER_LIMIT;
+    ap_daemons_limit = hard_server_limit;
     ap_pid_fname = DEFAULT_PIDLOG;
     ap_scoreboard_fname = DEFAULT_SCOREBOARD;
     ap_lock_fname = DEFAULT_LOCKFILE;
@@ -1282,17 +1293,16 @@
     }
 
     ap_daemons_limit = atoi(arg);
-    if (ap_daemons_limit > HARD_SERVER_LIMIT) {
+    if (ap_daemons_limit > hard_server_limit) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                    "WARNING: MaxClients of %d exceeds compile time limit "
-                    "of %d servers,", ap_daemons_limit, HARD_SERVER_LIMIT);
+                    "WARNING: MaxClients of %d exceeds HardServerLimit value "
+                    "of %d servers,", ap_daemons_limit, hard_server_limit);
        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
                     " lowering MaxClients to %d.  To increase, please "
-                    "see the", HARD_SERVER_LIMIT);
+                    "see the HardServerLimit", hard_server_limit);
        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
-                    " HARD_SERVER_LIMIT define in %s.",
-                    AP_MPM_HARD_LIMITS_FILE);
-       ap_daemons_limit = HARD_SERVER_LIMIT;
+                    " directive.");
+       ap_daemons_limit = hard_server_limit;
     } 
     else if (ap_daemons_limit < 1) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
@@ -1302,6 +1312,42 @@
     return NULL;
 }
 
+static const char *set_hard_server_limit (cmd_parms *cmd, void *dummy, const char 
+*arg) 
+{
+    int tmp_hard_server_limit;
+    
+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+    if (err != NULL) {
+        return err;
+    }
+
+    tmp_hard_server_limit = atoi(arg);
+    /* you cannot change HardServerLimit across a restart; ignore
+     * any such attempts
+     */
+    if (first_hard_server_limit &&
+        tmp_hard_server_limit != hard_server_limit) {
+        /* XXX how do we log a message?  the error log is a bit bucket at this point 
+*/
+        return NULL;
+    }
+    hard_server_limit = tmp_hard_server_limit;
+    
+    if (hard_server_limit > MAX_HARD_SERVER_LIMIT) {
+       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+                    "WARNING: HardServerLimit of %d exceeds compile time limit "
+                    "of %d servers,", hard_server_limit, MAX_HARD_SERVER_LIMIT);
+       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+                    " lowering HardServerLimit to %d.", MAX_HARD_SERVER_LIMIT);
+       hard_server_limit = MAX_HARD_SERVER_LIMIT;
+    } 
+    else if (hard_server_limit < 1) {
+       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
+                     "WARNING: Require HardServerLimit > 0, setting to 1");
+       hard_server_limit = 1;
+    }
+    return NULL;
+}
+
 static const command_rec prefork_cmds[] = {
 UNIX_DAEMON_COMMANDS,
 LISTEN_COMMANDS,
@@ -1313,6 +1359,8 @@
               "Maximum number of idle children"),
 AP_INIT_TAKE1("MaxClients", set_server_limit, NULL, RSRC_CONF,
               "Maximum number of children alive at the same time"),
+AP_INIT_TAKE1("HardServerLimit", set_hard_server_limit, NULL, RSRC_CONF,
+              "Maximum value of MaxClients for this run of Apache"),
 { NULL }
 };
 

-- 
Jeff Trawick | [EMAIL PROTECTED] | PGP public key at web site:
       http://www.geocities.com/SiliconValley/Park/9289/
             Born in Roswell... married an alien...

Reply via email to