httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From traw...@apache.org
Subject cvs commit: httpd-2.0/server/mpm/perchild perchild.c
Date Sun, 23 Dec 2001 14:22:36 GMT
trawick     01/12/23 06:22:36

  Modified:    .        CHANGES
               server/mpm/perchild perchild.c
  Log:
  add ThreadLimit/ServerLimit to perchild
  
  Revision  Changes    Path
  1.482     +3 -2      httpd-2.0/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/CHANGES,v
  retrieving revision 1.481
  retrieving revision 1.482
  diff -u -r1.481 -r1.482
  --- CHANGES	2001/12/20 20:25:47	1.481
  +++ CHANGES	2001/12/23 14:22:36	1.482
  @@ -1,4 +1,5 @@
   Changes with Apache 2.0.30-dev
  +
     *) Win32: Made change to apr_sendfile() to return APR_ENOTIMPL
        if oslevel < WINNT.  This should fix several problems reported
        Against 2.0.28 on Windows 98 [Bill Stoddard]
  @@ -7,8 +8,8 @@
        to fail. [Bill Stoddard]
   
     *) Change core code to allow an MPM to set hard thread/server
  -     limits at startup.  prefork and worker MPMs now have directives
  -     to set these limits.  [Jeff Trawick]
  +     limits at startup.  prefork, worker, and perchild MPMs now have 
  +     directives to set these limits.  [Jeff Trawick]
   
     *) Win32: The async AcceptEx() event should be autoreset upon
        successful completion of a wait (WaitForSingleObject). This
  
  
  
  1.96      +185 -49   httpd-2.0/server/mpm/perchild/perchild.c
  
  Index: perchild.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/mpm/perchild/perchild.c,v
  retrieving revision 1.95
  retrieving revision 1.96
  diff -u -r1.95 -r1.96
  --- perchild.c	2001/12/22 23:53:49	1.95
  +++ perchild.c	2001/12/23 14:22:36	1.96
  @@ -114,20 +114,24 @@
   #define AP_PERCHILD_THISCHILD -1
   #define AP_PERCHILD_OTHERCHILD -2
   
  -#define AP_ID_FROM_CHILD_THREAD(c, t)    ((c * HARD_THREAD_LIMIT) + t)
  -#define AP_CHILD_THREAD_FROM_ID(i)    (i / HARD_THREAD_LIMIT), (i % HARD_THREAD_LIMIT)
  -
   /* Limit on the threads per process.  Clients will be locked out if more than
  - * this  * HARD_SERVER_LIMIT are needed.
  + * this * server_limit are needed.
    *
    * We keep this for one reason it keeps the size of the scoreboard file small
    * enough that we can read the whole thing without worrying too much about
    * the overhead.
    */
  -#ifndef HARD_THREAD_LIMIT
  -#define HARD_THREAD_LIMIT 64 
  +#ifndef DEFAULT_THREAD_LIMIT
  +#define DEFAULT_THREAD_LIMIT 64 
   #endif
   
  +/* Admin can't tune ThreadLimit beyond MAX_THREAD_LIMIT.  We want
  + * some sort of compile-time limit to help catch typos.
  + */
  +#ifndef MAX_THREAD_LIMIT
  +#define MAX_THREAD_LIMIT 20000
  +#endif 
  +
   /* Limit on the total --- clients will be locked out if more servers than
    * this are needed.  It is intended solely to keep the server from crashing
    * when things get out of hand.
  @@ -139,10 +143,17 @@
    * enough that we can read the whole thing without worrying too much about
    * the overhead.
    */
  -#ifndef HARD_SERVER_LIMIT
  -#define HARD_SERVER_LIMIT 8 
  +#ifndef DEFAULT_SERVER_LIMIT
  +#define DEFAULT_SERVER_LIMIT 8 
   #endif
   
  +/* Admin can't tune ServerLimit beyond MAX_SERVER_LIMIT.  We want
  + * some sort of compile-time limit to help catch typos.
  + */
  +#ifndef MAX_SERVER_LIMIT
  +#define MAX_SERVER_LIMIT 20000
  +#endif
  +
   /*
    * Actual definitions of config globals
    */
  @@ -151,6 +162,11 @@
   static int min_spare_threads = 0;
   static int max_spare_threads = 0;
   static int max_threads = 0;
  +static int server_limit = DEFAULT_SERVER_LIMIT;
  +static int first_server_limit;
  +static int thread_limit = DEFAULT_THREAD_LIMIT;
  +static int first_thread_limit;
  +static int changed_limit_at_restart;
   static int max_requests_per_child = 0;
   static int num_daemons = 0;
   static int curr_child_num = 0;
  @@ -179,12 +195,10 @@
    * run as.  The hash table is used to correlate a server name with a child
    * process.
    */
  -static child_info_t child_info_table[HARD_SERVER_LIMIT];
  -static int          thread_socket_table[HARD_THREAD_LIMIT];
  -
  +static child_info_t *child_info_table;
  +static int          *thread_socket_table;
  +struct ap_ctable    *ap_child_table;
   
  -struct ap_ctable    ap_child_table[HARD_SERVER_LIMIT];
  -
   /*
    * The max child slot ever assigned, preserved across restarts.  Necessary
    * to deal with NumServers changes across AP_SIG_GRACEFUL restarts.  We 
  @@ -195,7 +209,7 @@
    * many child processes in this MPM.
    */
   int ap_max_daemons_limit = -1;
  -int ap_threads_per_child = HARD_THREAD_LIMIT;
  +int ap_threads_per_child; /* XXX not part of API!  axe it! */
   
   module AP_MODULE_DECLARE_DATA mpm_perchild_module;
   
  @@ -235,7 +249,7 @@
   /* Keep track of the number of worker threads currently active */
   static int worker_thread_count;
   static apr_lock_t *worker_thread_count_mutex;
  -static int worker_thread_free_ids[HARD_THREAD_LIMIT];
  +static int *worker_thread_free_ids;
   static apr_threadattr_t *worker_thread_attr;
   
   /* Keep track of the number of idle worker threads */
  @@ -264,10 +278,10 @@
               *result = AP_MPMQ_STATIC;
               return APR_SUCCESS;
           case AP_MPMQ_HARD_LIMIT_DAEMONS:
  -            *result = HARD_SERVER_LIMIT;
  +            *result = server_limit;
               return APR_SUCCESS;
           case AP_MPMQ_HARD_LIMIT_THREADS:
  -            *result = HARD_THREAD_LIMIT;
  +            *result = thread_limit;
               return APR_SUCCESS;
           case AP_MPMQ_MAX_THREADS:
               *result = max_threads;
  @@ -531,7 +545,7 @@
       conn_rec *current_conn;
       int csd;
       apr_status_t rv;
  -    int thread_num = conn_id % HARD_THREAD_LIMIT;
  +    int thread_num = conn_id % thread_limit;
       void *sbh;
   
       if ((rv = apr_os_sock_get(&csd, sock)) != APR_SUCCESS) {
  @@ -552,7 +566,7 @@
           ap_sock_disable_nagle(sock);
       }
   
  -    ap_create_sb_handle(&sbh, p, conn_id / HARD_THREAD_LIMIT, thread_num);
  +    ap_create_sb_handle(&sbh, p, conn_id / thread_limit, thread_num);
       current_conn = ap_run_create_connection(p, ap_server_conf, sock, conn_id, sbh);
       if (current_conn) {
           ap_process_connection(current_conn);
  @@ -641,7 +655,7 @@
       int srv;
       int curr_pollfd;
       int thread_num = *((int *) arg);
  -    long conn_id = child_num * HARD_THREAD_LIMIT + thread_num;
  +    long conn_id = child_num * thread_limit + thread_num;
       apr_pollfd_t *pollset;
       int n;
       apr_status_t rv;
  @@ -992,6 +1006,7 @@
       }
       idle_thread_count = threads_to_start;
       worker_thread_count = 0;
  +    worker_thread_free_ids = (int *)apr_pcalloc(pchild, thread_limit * sizeof(int));
       for (i = 0; i < max_threads; i++) {
           worker_thread_free_ids[i] = i;
       }
  @@ -1244,6 +1259,15 @@
   
       pconf = _pconf;
       ap_server_conf = s;
  +    first_server_limit = server_limit;
  +    first_thread_limit = thread_limit;
  +    if (changed_limit_at_restart) {
  +        ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, 0, s,
  +                     "WARNING: Attempt to change ServerLimit or ThreadLimit "
  +                     "ignored during restart");
  +        changed_limit_at_restart = 0;
  +    }
  +
       if ((rv = apr_file_pipe_create(&pipe_of_death_in, &pipe_of_death_out,
                                      pconf)) != APR_SUCCESS) {
           ap_log_error(APLOG_MARK, APLOG_ERR, rv,
  @@ -1285,7 +1309,7 @@
       }
       /* Initialize the child table */
       if (!is_graceful) {
  -        for (i = 0; i < HARD_SERVER_LIMIT; i++) {
  +        for (i = 0; i < server_limit; i++) {
               ap_child_table[i].pid = 0;
           }
       }
  @@ -1402,7 +1426,10 @@
   {
       static int restart_num = 0;
       int no_detach, debug;
  +    ap_directive_t *pdir;
       int i;
  +    int tmp_server_limit = DEFAULT_SERVER_LIMIT;
  +    int tmp_thread_limit = DEFAULT_THREAD_LIMIT;
   
       debug = ap_exists_config_define("DEBUG");
   
  @@ -1431,7 +1458,7 @@
       threads_to_start = DEFAULT_START_THREAD;
       min_spare_threads = DEFAULT_MIN_SPARE_THREAD;
       max_spare_threads = DEFAULT_MAX_SPARE_THREAD;
  -    max_threads = HARD_THREAD_LIMIT;
  +    max_threads = thread_limit;
       ap_pid_fname = DEFAULT_PIDLOG;
       ap_scoreboard_fname = DEFAULT_SCOREBOARD;
       ap_lock_fname = DEFAULT_LOCKFILE;
  @@ -1440,14 +1467,34 @@
   
       apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
   
  -    for (i = 0; i < HARD_SERVER_LIMIT; i++) {
  +    /* we need to know ServerLimit and ThreadLimit before we start processing
  +     * the tree because we need to already have allocated child_info_table
  +     */
  +    for (pdir = ap_conftree; pdir != NULL; pdir = pdir->next) {
  +        if (!strcasecmp(pdir->directive, "ServerLimit")) {
  +            if (atoi(pdir->args) > tmp_server_limit) {
  +                tmp_server_limit = atoi(pdir->args);
  +                if (tmp_server_limit > MAX_SERVER_LIMIT) {
  +                    tmp_server_limit = MAX_SERVER_LIMIT;
  +                }
  +            }
  +        }
  +        else if (!strcasecmp(pdir->directive, "ThreadLimit")) {
  +            if (atoi(pdir->args) > tmp_thread_limit) {
  +                tmp_thread_limit = atoi(pdir->args);
  +                if (tmp_thread_limit > MAX_THREAD_LIMIT) {
  +                    tmp_thread_limit = MAX_THREAD_LIMIT;
  +                }
  +            }
  +        }
  +    }
  +
  +    child_info_table = (child_info_t *)apr_pcalloc(p, tmp_server_limit * sizeof(child_info_t));
  +    for (i = 0; i < tmp_server_limit; i++) {
           child_info_table[i].uid = -1;
           child_info_table[i].gid = -1;
           child_info_table[i].sd = -1;
       }
  -    for (i = 0; i < HARD_THREAD_LIMIT; i++) {
  -        thread_socket_table[i] = AP_PERCHILD_THISCHILD;
  -    }
   }
   
   static int pass_request(request_rec *r)
  @@ -1524,14 +1571,13 @@
       return NULL;
   }
   
  -
   static int perchild_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec
*s)
   {
       int i;
       server_rec *sr;
       perchild_server_conf *sconf;
       int def_sd[2];
  -    
  +
       def_sd[0] = -1;
       def_sd[1] = -1;
   
  @@ -1557,13 +1603,20 @@
               child_info_table[i].sd = def_sd[0];
           }
       }
  +
  +    thread_socket_table = (int *)apr_pcalloc(p, thread_limit * sizeof(int));
  +    for (i = 0; i < thread_limit; i++) {
  +        thread_socket_table[i] = AP_PERCHILD_THISCHILD;
  +    }
  +    ap_child_table = (ap_ctable *)apr_pcalloc(p, server_limit * sizeof(ap_ctable));
  +
       return OK;
   }
   
   static int perchild_post_read(request_rec *r)
   {
       ap_filter_t *f = r->connection->input_filters;
  -    int thread_num = r->connection->id % HARD_THREAD_LIMIT;
  +    int thread_num = r->connection->id % thread_limit;
       perchild_server_conf *sconf = (perchild_server_conf *)
                               ap_get_module_config(r->server->module_config, 
                                                    &mpm_perchild_module);
  @@ -1670,17 +1723,16 @@
       }
   
       num_daemons = atoi(arg);
  -    if (num_daemons > HARD_SERVER_LIMIT) {
  +    if (num_daemons > server_limit) {
          ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  -                    "WARNING: NumServers of %d exceeds compile time limit "
  -                    "of %d servers,", num_daemons, HARD_SERVER_LIMIT);
  +                    "WARNING: NumServers of %d exceeds ServerLimit value "
  +                    "of %d servers,", num_daemons, server_limit);
          ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
                       " lowering NumServers to %d.  To increase, please "
  -                    "see the", HARD_SERVER_LIMIT);
  +                    "see the", server_limit);
          ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  -                    " HARD_SERVER_LIMIT define in %s.",
  -                    AP_MPM_HARD_LIMITS_FILE);
  -       num_daemons = HARD_SERVER_LIMIT;
  +                    " ServerLimit directive.");
  +       num_daemons = server_limit;
       } 
       else if (num_daemons < 1) {
           ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  @@ -1699,17 +1751,16 @@
       }
   
       threads_to_start = atoi(arg);
  -    if (threads_to_start > HARD_THREAD_LIMIT) {
  +    if (threads_to_start > thread_limit) {
           ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  -                     "WARNING: StartThreads of %d exceeds compile time"
  -                     " limit of %d threads,", threads_to_start,
  -                     HARD_THREAD_LIMIT);
  +                     "WARNING: StartThreads of %d exceeds ThreadLimit value"
  +                     " of %d threads,", threads_to_start,
  +                     thread_limit);
           ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
                        " lowering StartThreads to %d. To increase, please"
  -                     " see the", HARD_THREAD_LIMIT);
  +                     " see the", thread_limit);
           ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  -                     " HARD_THREAD_LIMIT define in %s.",
  -                     AP_MPM_HARD_LIMITS_FILE);
  +                     " ThreadLimit directive.");
       }
       else if (threads_to_start < 1) {
           ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  @@ -1750,12 +1801,12 @@
       }
   
       max_spare_threads = atoi(arg);
  -    if (max_spare_threads >= HARD_THREAD_LIMIT) {
  +    if (max_spare_threads >= thread_limit) {
          ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
                       "WARNING: detected MinSpareThreads set higher than");
          ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  -                    "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
  -       max_spare_threads = HARD_THREAD_LIMIT;
  +                    "ThreadLimit. Resetting to %d", thread_limit);
  +       max_spare_threads = thread_limit;
       }
       return NULL;
   }
  @@ -1768,12 +1819,12 @@
       }
   
       max_threads = atoi(arg);
  -    if (max_threads > HARD_THREAD_LIMIT) {
  +    if (max_threads > thread_limit) {
          ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
                       "WARNING: detected MaxThreadsPerChild set higher than");
          ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  -                    "HARD_THREAD_LIMIT. Resetting to %d", HARD_THREAD_LIMIT);
  -       max_threads = HARD_THREAD_LIMIT;
  +                    "ThreadLimit. Resetting to %d", thread_limit);
  +       max_threads = thread_limit;
       }
       return NULL;
   }
  @@ -1783,6 +1834,7 @@
   {
       int i;
       int max_this_time = atoi(num) + curr_child_num;
  +
       for (i = curr_child_num; i < max_this_time; i++, curr_child_num++) {
           child_info_t *ug = &child_info_table[i - 1];
   
  @@ -1828,6 +1880,86 @@
       return NULL;
   }
   
  +static const char *set_server_limit (cmd_parms *cmd, void *dummy, const char *arg) 
  +{
  +    int tmp_server_limit;
  +    
  +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  +    if (err != NULL) {
  +        return err;
  +    }
  +
  +    tmp_server_limit = atoi(arg);
  +    /* you cannot change ServerLimit across a restart; ignore
  +     * any such attempts
  +     */
  +    if (first_server_limit &&
  +        tmp_server_limit != server_limit) {
  +        /* how do we log a message?  the error log is a bit bucket at this
  +         * point; we'll just have to set a flag so that ap_mpm_run()
  +         * logs a warning later
  +         */
  +        changed_limit_at_restart = 1;
  +        return NULL;
  +    }
  +    server_limit = tmp_server_limit;
  +    
  +    if (server_limit > MAX_SERVER_LIMIT) {
  +       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  +                    "WARNING: ServerLimit of %d exceeds compile time limit "
  +                    "of %d servers,", server_limit, MAX_SERVER_LIMIT);
  +       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  +                    " lowering ServerLimit to %d.", MAX_SERVER_LIMIT);
  +       server_limit = MAX_SERVER_LIMIT;
  +    } 
  +    else if (server_limit < 1) {
  +	ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  +                     "WARNING: Require ServerLimit > 0, setting to 1");
  +	server_limit = 1;
  +    }
  +    return NULL;
  +}
  +
  +static const char *set_thread_limit (cmd_parms *cmd, void *dummy, const char *arg) 
  +{
  +    int tmp_thread_limit;
  +    
  +    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  +    if (err != NULL) {
  +        return err;
  +    }
  +
  +    tmp_thread_limit = atoi(arg);
  +    /* you cannot change ThreadLimit across a restart; ignore
  +     * any such attempts
  +     */
  +    if (first_thread_limit &&
  +        tmp_thread_limit != thread_limit) {
  +        /* how do we log a message?  the error log is a bit bucket at this
  +         * point; we'll just have to set a flag so that ap_mpm_run()
  +         * logs a warning later
  +         */
  +        changed_limit_at_restart = 1;
  +        return NULL;
  +    }
  +    thread_limit = tmp_thread_limit;
  +    
  +    if (thread_limit > MAX_THREAD_LIMIT) {
  +       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  +                    "WARNING: ThreadLimit of %d exceeds compile time limit "
  +                    "of %d servers,", thread_limit, MAX_THREAD_LIMIT);
  +       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  +                    " lowering ThreadLimit to %d.", MAX_THREAD_LIMIT);
  +       thread_limit = MAX_THREAD_LIMIT;
  +    } 
  +    else if (thread_limit < 1) {
  +	ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
  +                     "WARNING: Require ThreadLimit > 0, setting to 1");
  +	thread_limit = 1;
  +    }
  +    return NULL;
  +}
  +
   static const command_rec perchild_cmds[] = {
   UNIX_DAEMON_COMMANDS,
   LISTEN_COMMANDS,
  @@ -1846,6 +1978,10 @@
                 "Specify a User and Group for a specific child process."),
   AP_INIT_TAKE2("AssignUserID", assign_childuid, NULL, RSRC_CONF,
                 "Tie a virtual host to a specific child process."),
  +AP_INIT_TAKE1("ServerLimit", set_server_limit, NULL, RSRC_CONF,
  +              "Maximum value of NumServers for this run of Apache"),
  +AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
  +              "Maximum worker threads in a server for this run of Apache"),
   { NULL }
   };
   
  
  
  

Mime
View raw message