ASF Bugzilla – Attachment 31126 Details for
Bug 55897
[PATCH]patch with SO_REUSEPORT support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
[PATCH]prefork_mpm patch with SO_REUSEPORT support
unified.diff.httpd-2.4.7.patch (text/plain), 25.17 KB, created by
Yingqi.Lu
on 2013-12-17 17:39:55 UTC
(
hide
)
Description:
[PATCH]prefork_mpm patch with SO_REUSEPORT support
Filename:
MIME Type:
Creator:
Yingqi.Lu
Created:
2013-12-17 17:39:55 UTC
Size:
25.17 KB
patch
obsolete
>Only in httpd-2.4.7.new: 1 >diff -ru httpd-2.4.7/configure httpd-2.4.7.new/configure >--- httpd-2.4.7/configure 2013-11-19 12:36:02.000000000 -0500 >+++ httpd-2.4.7.new/configure 2013-12-15 12:32:24.151998734 -0500 >@@ -6354,7 +6354,20 @@ > > APACHE_VAR_SUBST="$APACHE_VAR_SUBST LTCFLAGS" > >+case $host in >+ *-linux-*) >+ case `uname -r` in >+ # SO_REUSEPORT feature is only being enabled in the Linux kernel newer than 3.9 >+ [0-2].* | 3.[0-8].*) >+ ;; >+ * ) >+ test "x$silent" != "xyes" && echo " forcing HAVE_SO_REUSEPORT to \"1\"" >+ HAVE_SO_REUSEPORT="1" > >+ ;; >+ esac >+ ;; >+esac > > case $host in > *-apple-aux3*) >@@ -32191,6 +32204,12 @@ > > fi > >+if test "$HAVE_SO_REUSEPORT" = "1"; then >+ >+$as_echo "#define HAVE_SO_REUSEPORT 1" >>confdefs.h >+ >+fi >+ > if test "$AP_NONBLOCK_WHEN_MULTI_LISTEN" = "1"; then > > $as_echo "#define AP_NONBLOCK_WHEN_MULTI_LISTEN 1" >>confdefs.h >diff -ru httpd-2.4.7/configure.in httpd-2.4.7.new/configure.in >--- httpd-2.4.7/configure.in 2013-08-19 11:42:37.000000000 -0400 >+++ httpd-2.4.7.new/configure.in 2013-12-15 12:32:31.207998621 -0500 >@@ -307,6 +307,19 @@ > APACHE_SUBST(LTCFLAGS) > > case $host in >+ *-linux-*) >+ case `uname -r` in >+ #SO_REUSEPORT is only being enabled in Linux kernel 3.9 and newer >+ [[0-2]].* | 3.[[0-8]].* ) >+ ;; >+ * ) >+ APR_SETVAR(HAVE_SO_REUSEPORT, [1]) >+ ;; >+ esac >+ ;; >+esac >+ >+case $host in > *-apple-aux3*) > APR_SETVAR(SINGLE_LISTEN_UNSERIALIZED_ACCEPT, [1]) > ;; >@@ -761,6 +774,11 @@ > [This platform doesn't suffer from the thundering herd problem]) > fi > >+if test "$HAVE_SO_REUSEPORT" = "1"; then >+ AC_DEFINE(HAVE_SO_REUSEPORT, 1, >+ [This platform has SO_REUSEPORT feature enabled]) >+fi >+ > if test "$AP_NONBLOCK_WHEN_MULTI_LISTEN" = "1"; then > AC_DEFINE(AP_NONBLOCK_WHEN_MULTI_LISTEN, 1, > [Listening sockets are non-blocking when there are more than 1]) >diff -ru httpd-2.4.7/include/ap_config_auto.h.in httpd-2.4.7.new/include/ap_config_auto.h.in >--- httpd-2.4.7/include/ap_config_auto.h.in 2013-11-19 12:36:01.000000000 -0500 >+++ httpd-2.4.7.new/include/ap_config_auto.h.in 2013-12-15 12:33:03.447998106 -0500 >@@ -229,6 +229,9 @@ > /* This platform doesn't suffer from the thundering herd problem */ > #undef SINGLE_LISTEN_UNSERIALIZED_ACCEPT > >+/* Define to 1 if you have SO_REUSEPORT enabled in your kernel. Linux kernel newer than 3.9 has this enabled */ >+#undef HAVE_SO_REUSEPORT >+ > /* Define to 1 if you have the ANSI C header files. */ > #undef STDC_HEADERS > >diff -ru httpd-2.4.7/include/ap_listen.h httpd-2.4.7.new/include/ap_listen.h >--- httpd-2.4.7/include/ap_listen.h 2011-09-23 14:08:42.000000000 -0400 >+++ httpd-2.4.7.new/include/ap_listen.h 2013-12-17 08:33:54.396964779 -0500 >@@ -79,6 +79,15 @@ > AP_DECLARE_DATA extern ap_listen_rec *ap_listeners; > > /** >+ ** The listener array defined for the patch. >+ ** */ >+AP_DECLARE_DATA extern ap_listen_rec **mpm_listen; >+ >+AP_DECLARE_DATA extern int flag; >+ >+AP_DECLARE_DATA extern int num_buckets; >+ >+/** > * Setup all of the defaults for the listener list > */ > AP_DECLARE(void) ap_listen_pre_config(void); >@@ -91,6 +100,15 @@ > */ > AP_DECLARE(int) ap_setup_listeners(server_rec *s); > >+/**This function is added for the patch. It creates sockets for the mpm_listen >+ * array, executes the listen and bind on the sockets, and set the sockets to >+ * be active. If HAVE_SO_REUSEPORT is enabled, It will duplicate ap_listeners. >+ * @param s The global server_rec >+ * @param p The config pool >+ * @param num_buckets The total number of listener buckets. >+ * */ >+AP_DECLARE(apr_status_t) ap_post_config_listeners(server_rec *s, apr_pool_t *p, int num_buckets); >+ > /** > * Loop through the global ap_listen_rec list and close each of the sockets. > */ >diff -ru httpd-2.4.7/server/listen.c httpd-2.4.7.new/server/listen.c >--- httpd-2.4.7/server/listen.c 2012-12-12 09:19:54.000000000 -0500 >+++ httpd-2.4.7.new/server/listen.c 2013-12-17 10:33:01.124993652 -0500 >@@ -34,6 +34,10 @@ > > AP_DECLARE_DATA ap_listen_rec *ap_listeners = NULL; > >+AP_DECLARE_DATA ap_listen_rec **mpm_listen = NULL; >+AP_DECLARE_DATA int flag = 1; >+AP_DECLARE_DATA int num_buckets = 1; >+ > static ap_listen_rec *old_listeners; > static int ap_listenbacklog; > static int send_buffer_size; >@@ -131,21 +135,34 @@ > ap_sock_disable_nagle(s); > #endif > >- if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) { >- ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p, APLOGNO(00072) >- "make_sock: could not bind to address %pI", >+#if HAVE_SO_REUSEPORT >+ if((stat = apr_socket_opt_set(s, APR_SO_REUSEPORT, one)) != APR_SUCCESS) { >+ ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, p, APLOGNO(09999) >+ "make_sock: for address %pI, apr_socket_opt_set: " >+ "(SO_REUSEPORT)", > server->bind_addr); > apr_socket_close(s); >- return stat; >+ return stat; /*need to fix the APLOGNO */ > } >+#endif > >- if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) { >- ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p, APLOGNO(00073) >- "make_sock: unable to listen for connections " >- "on address %pI", >- server->bind_addr); >- apr_socket_close(s); >- return stat; >+ if (flag) { >+ if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) { >+ ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p, APLOGNO(00072) >+ "make_sock: could not bind to address %pI", >+ server->bind_addr); >+ apr_socket_close(s); >+ return stat; >+ } >+ >+ if ((stat = apr_socket_listen(s, ap_listenbacklog)) != APR_SUCCESS) { >+ ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, stat, p, APLOGNO(00073) >+ "make_sock: unable to listen for connections " >+ "on address %pI", >+ server->bind_addr); >+ apr_socket_close(s); >+ return stat; >+ } > } > > #ifdef WIN32 >@@ -170,8 +187,12 @@ > #endif > > server->sd = s; >- server->active = 1; >- >+ if (flag) { >+ server->active = 1; >+ } >+ else { >+ server->active = 0; >+ } > server->accept_func = NULL; > > return APR_SUCCESS; >@@ -233,6 +254,87 @@ > } > } > >+static ap_listen_rec* ap_duplicate_listener(server_rec *s, apr_pool_t *p, >+ ap_listen_rec *lr) >+{ >+ apr_status_t stat; >+ int use_nonblock = 0; >+ ap_listen_rec *duplr; >+ duplr = apr_palloc(p, sizeof(ap_listen_rec)); >+ duplr->slave = 0; >+ duplr->protocol = apr_pstrdup(p, lr->protocol); >+ apr_sockaddr_t *sa; >+ char *hostname; >+ apr_port_t port; >+ hostname = apr_pstrdup(p, lr->bind_addr->hostname); >+ port = lr->bind_addr->port; >+ apr_sockaddr_info_get(&sa, hostname, APR_UNSPEC, port, 0, p); >+ duplr->bind_addr = sa; >+ duplr->next = 0; >+ apr_socket_t *temps; >+ if ((stat = apr_socket_create(&temps, duplr->bind_addr->family, >+ SOCK_STREAM, 0, p)) != APR_SUCCESS) { >+ ap_log_perror(APLOG_MARK, APLOG_CRIT, 0, p, APLOGNO(09999) >+ "ap_duplicate_socket: for address %pI, " >+ "cannot duplicate a new socket!", >+ duplr->bind_addr); /*need to fix the APLOGNO */ >+ return NULL; >+ } >+ duplr->sd = temps; >+ flag = 1; >+ stat = make_sock(p, duplr); >+/* duplicate from open_listeners()*/ >+#if AP_NONBLOCK_WHEN_MULTI_LISTEN >+ if ((stat = apr_socket_opt_set(duplr->sd, APR_SO_NONBLOCK, 1)) >+ != APR_SUCCESS) { >+ ap_log_perror(APLOG_MARK, APLOG_CRIT, stat, p, APLOGNO(09999) >+ "unable to control socket non-blocking status"); >+ return NULL; >+ } /*need to fix the APLOGNO */ >+#endif >+ return duplr; >+} >+ >+/* This function is added for the patch. This function duplicates >+ * open_listeners, alloc_listener() and re-call make_sock() for the >+ * duplicated listeners. In this function, the newly created sockets >+ * will bind and listen*/ >+AP_DECLARE(apr_status_t) ap_post_config_listeners(server_rec *s, apr_pool_t *p, >+ int num_buckets) { >+ mpm_listen = apr_palloc(p, sizeof(ap_listen_rec*) * num_buckets); >+ int i; >+ ap_listen_rec *lr; >+/* duplicate from alloc_listener() for the additional listen record*/ >+#ifndef HAVE_SO_REUSEPORT >+ lr = ap_listeners; >+#endif >+ for (i = 0; i < num_buckets; i++) { >+#ifdef HAVE_SO_REUSEPORT >+ ap_listen_rec *templr; >+ lr = ap_listeners; >+ ap_listen_rec *last = NULL; >+ while (lr) { >+ templr = ap_duplicate_listener(s, p, lr); >+ >+ ap_apply_accept_filter(p, templr, s); >+ >+ if (last == NULL) { >+ mpm_listen[i] = last = templr; >+ } >+ else { >+ last->next = templr; >+ last = templr; >+ } >+ lr = lr->next; >+ } >+#else >+ mpm_listen[i] = ap_duplicate_listener(s, p, lr); >+ lr = lr->next; >+#endif >+ } >+ return APR_SUCCESS; >+} >+ > static apr_status_t close_listeners_on_exec(void *v) > { > ap_close_listeners(); >@@ -585,11 +687,18 @@ > AP_DECLARE_NONSTD(void) ap_close_listeners(void) > { > ap_listen_rec *lr; >+ int i; > > for (lr = ap_listeners; lr; lr = lr->next) { > apr_socket_close(lr->sd); > lr->active = 0; > } >+ for (i = 0; i < num_buckets; i++) { >+ for (lr = mpm_listen[i]; lr; lr = lr->next) { >+ apr_socket_close(lr->sd); >+ lr->active = 0; >+ } >+ } > } > AP_DECLARE_NONSTD(int) ap_close_selected_listeners(ap_slave_t *slave) > { >diff -ru httpd-2.4.7/server/mpm/prefork/prefork.c httpd-2.4.7.new/server/mpm/prefork/prefork.c >--- httpd-2.4.7/server/mpm/prefork/prefork.c 2012-10-03 06:03:32.000000000 -0400 >+++ httpd-2.4.7.new/server/mpm/prefork/prefork.c 2013-12-17 09:12:46.148927507 -0500 >@@ -86,7 +86,7 @@ > > /* config globals */ > >-static apr_proc_mutex_t *accept_mutex; >+static apr_proc_mutex_t **accept_mutex; > static int ap_daemons_to_start=0; > static int ap_daemons_min_free=0; > static int ap_daemons_max_free=0; >@@ -94,6 +94,7 @@ > static int server_limit = 0; > static int mpm_state = AP_MPMQ_STARTING; > static ap_pod_t *pod; >+int *bucket; /* bucket array for the httpd child processes */ > > /* data retained by prefork across load/unload of the module > * allocated on first call to pre-config hook; located on >@@ -117,7 +118,7 @@ > * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by > * without the need to spawn. > */ >- int idle_spawn_rate; >+ int idle_spawn_rate[1025]; > #ifndef MAX_SPAWN_RATE > #define MAX_SPAWN_RATE (32) > #endif >@@ -227,9 +228,9 @@ > exit(code); > } > >-static void accept_mutex_on(void) >+static void accept_mutex_on(apr_proc_mutex_t *mutex) > { >- apr_status_t rv = apr_proc_mutex_lock(accept_mutex); >+ apr_status_t rv = apr_proc_mutex_lock(mutex); > if (rv != APR_SUCCESS) { > const char *msg = "couldn't grab the accept mutex"; > >@@ -245,9 +246,9 @@ > } > } > >-static void accept_mutex_off(void) >+static void accept_mutex_off(apr_proc_mutex_t *mutex) > { >- apr_status_t rv = apr_proc_mutex_unlock(accept_mutex); >+ apr_status_t rv = apr_proc_mutex_unlock(mutex); > if (rv != APR_SUCCESS) { > const char *msg = "couldn't release the accept mutex"; > >@@ -271,10 +272,10 @@ > * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT > * when it's safe in the single Listen case. > */ >-#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT >-#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0) >-#else >+#if !defined (SINGLE_LISTEN_UNSERIALIZED_ACCEPT) || defined (HAVE_SO_REUSEPORT) > #define SAFE_ACCEPT(stmt) do {stmt;} while(0) >+#else >+#define SAFE_ACCEPT(stmt) do {if (ap_listeners->next) {stmt;}} while(0) > #endif > > static int prefork_query(int query_code, int *result, apr_status_t *rv) >@@ -523,8 +524,8 @@ > > /* needs to be done before we switch UIDs so we have permissions */ > ap_reopen_scoreboard(pchild, NULL, 0); >- lockfile = apr_proc_mutex_lockfile(accept_mutex); >- status = apr_proc_mutex_child_init(&accept_mutex, >+ lockfile = apr_proc_mutex_lockfile(accept_mutex[bucket[my_child_num]]); >+ status = apr_proc_mutex_child_init(&accept_mutex[bucket[my_child_num]], > lockfile, > pchild); > if (status != APR_SUCCESS) { >@@ -532,7 +533,7 @@ > "Couldn't initialize cross-process lock in child " > "(%s) (%s)", > lockfile ? lockfile : "none", >- apr_proc_mutex_name(accept_mutex)); >+ apr_proc_mutex_name(accept_mutex[bucket[my_child_num]])); > clean_child_exit(APEXIT_CHILDFATAL); > } > >@@ -554,7 +555,7 @@ > clean_child_exit(APEXIT_CHILDSICK); /* assume temporary resource issue */ > } > >- for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) { >+ for (lr = mpm_listen[bucket[my_child_num]], i = num_listensocks; i--; lr = lr->next) { > apr_pollfd_t pfd = { 0 }; > > pfd.desc_type = APR_POLL_SOCKET; >@@ -608,11 +609,11 @@ > */ > > /* Lock around "accept", if necessary */ >- SAFE_ACCEPT(accept_mutex_on()); >+ SAFE_ACCEPT(accept_mutex_on(accept_mutex[bucket[my_child_num]])); > > if (num_listensocks == 1) { > /* There is only one listener record, so refer to that one. */ >- lr = ap_listeners; >+ lr = mpm_listen[bucket[my_child_num]]; > } > else { > /* multiple listening sockets - need to poll */ >@@ -625,7 +626,7 @@ > */ > if (die_now /* in graceful stop/restart */ > || (one_process && shutdown_pending)) { >- SAFE_ACCEPT(accept_mutex_off()); >+ SAFE_ACCEPT(accept_mutex_off(accept_mutex[bucket[my_child_num]])); > clean_child_exit(0); > } > >@@ -647,7 +648,7 @@ > */ > ap_log_error(APLOG_MARK, APLOG_ERR, status, > ap_server_conf, APLOGNO(00158) "apr_pollset_poll: (listen)"); >- SAFE_ACCEPT(accept_mutex_off()); >+ SAFE_ACCEPT(accept_mutex_off(accept_mutex[bucket[my_child_num]])); > clean_child_exit(APEXIT_CHILDSICK); > } > >@@ -681,7 +682,7 @@ > */ > status = lr->accept_func(&csd, lr, ptrans); > >- SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */ >+ SAFE_ACCEPT(accept_mutex_off(accept_mutex[bucket[my_child_num]])); /* unlock after "accept" */ > > if (status == APR_EGENERAL) { > /* resource shortage or should-not-occur occured */ >@@ -750,7 +751,6 @@ > (void) ap_update_child_status_from_indexes(slot, 0, SERVER_STARTING, > (request_rec *) NULL); > >- > #ifdef _OSD_POSIX > /* BS2000 requires a "special" version of fork() before a setuid() call */ > if ((pid = os_fork(ap_unixd_config.user_name)) == -1) { >@@ -815,20 +815,23 @@ > if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) { > continue; > } >+ bucket[i] = i % num_buckets; > if (make_child(ap_server_conf, i) < 0) { > break; > } > --number_to_start; > } > } >- >-static void perform_idle_server_maintenance(apr_pool_t *p) >+/* >+* patch: execute idle server maintenance on each child group. >+*/ >+static void perform_idle_server_maintenance(apr_pool_t *p, int my_bucket) > { > int i; > int idle_count; > worker_score *ws; > int free_length; >- int free_slots[MAX_SPAWN_RATE]; >+ int free_slots[MAX_SPAWN_RATE/num_buckets]; > int last_non_dead; > int total_non_dead; > >@@ -842,13 +845,13 @@ > for (i = 0; i < ap_daemons_limit; ++i) { > int status; > >- if (i >= retained->max_daemons_limit && free_length == retained->idle_spawn_rate) >+ if (i >= retained->max_daemons_limit && free_length == retained->idle_spawn_rate[my_bucket]) > break; > ws = &ap_scoreboard_image->servers[i][0]; > status = ws->status; > if (status == SERVER_DEAD) { > /* try to keep children numbers as low as possible */ >- if (free_length < retained->idle_spawn_rate) { >+ if (free_length < retained->idle_spawn_rate[my_bucket]) { > free_slots[free_length] = i; > ++free_length; > } >@@ -860,7 +863,7 @@ > * So we hopefully won't need to fork more if we count it. > * This depends on the ordering of SERVER_READY and SERVER_STARTING. > */ >- if (status <= SERVER_READY) { >+ if ((status <= SERVER_READY) && (bucket[i] == my_bucket)) { > ++ idle_count; > } > >@@ -869,15 +872,15 @@ > } > } > retained->max_daemons_limit = last_non_dead + 1; >- if (idle_count > ap_daemons_max_free) { >+ if (idle_count > ap_daemons_max_free/num_buckets) { > /* kill off one child... we use the pod because that'll cause it to > * shut down gracefully, in case it happened to pick up a request > * while we were counting > */ > ap_mpm_pod_signal(pod); >- retained->idle_spawn_rate = 1; >+ retained->idle_spawn_rate[my_bucket] = 1; > } >- else if (idle_count < ap_daemons_min_free) { >+ else if (idle_count < ap_daemons_min_free/num_buckets) { > /* terminate the free list */ > if (free_length == 0) { > /* only report this condition once */ >@@ -887,18 +890,19 @@ > " raising the MaxRequestWorkers setting"); > retained->maxclients_reported = 1; > } >- retained->idle_spawn_rate = 1; >+ retained->idle_spawn_rate[my_bucket] = 1; > } > else { >- if (retained->idle_spawn_rate >= 8) { >+ if (retained->idle_spawn_rate[my_bucket] >= 8) { > ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00162) > "server seems busy, (you may need " > "to increase StartServers, or Min/MaxSpareServers), " > "spawning %d children, there are %d idle, and " >- "%d total children", retained->idle_spawn_rate, >+ "%d total children", retained->idle_spawn_rate[my_bucket], > idle_count, total_non_dead); > } > for (i = 0; i < free_length; ++i) { >+ bucket[free_slots[i]] = my_bucket; > make_child(ap_server_conf, free_slots[i]); > } > /* the next time around we want to spawn twice as many if this >@@ -907,13 +911,13 @@ > if (retained->hold_off_on_exponential_spawning) { > --retained->hold_off_on_exponential_spawning; > } >- else if (retained->idle_spawn_rate < MAX_SPAWN_RATE) { >- retained->idle_spawn_rate *= 2; >+ else if (retained->idle_spawn_rate[my_bucket] < MAX_SPAWN_RATE/num_buckets) { >+ retained->idle_spawn_rate[my_bucket] *= 2; > } > } > } > else { >- retained->idle_spawn_rate = 1; >+ retained->idle_spawn_rate[my_bucket] = 1; > } > } > >@@ -926,15 +930,20 @@ > int index; > int remaining_children_to_start; > apr_status_t rv; >+ int i; > > ap_log_pid(pconf, ap_pid_fname); > >- /* Initialize cross-process accept lock */ >- rv = ap_proc_mutex_create(&accept_mutex, NULL, AP_ACCEPT_MUTEX_TYPE, NULL, >- s, _pconf, 0); >- if (rv != APR_SUCCESS) { >- mpm_state = AP_MPMQ_STOPPING; >- return DONE; >+ bucket = apr_palloc(_pconf, sizeof(int) * ap_daemons_limit); >+ /* Initialize cross-process accept lock for each bucket*/ >+ accept_mutex = apr_palloc(_pconf, sizeof(apr_proc_mutex_t *) * num_buckets); >+ for (i = 0; i < num_buckets; i++) { >+ rv = ap_proc_mutex_create(&accept_mutex[i], NULL, AP_ACCEPT_MUTEX_TYPE, NULL, >+ s, _pconf, 0); >+ if (rv != APR_SUCCESS) { >+ mpm_state = AP_MPMQ_STOPPING; >+ return DONE; >+ } > } > > if (!retained->is_graceful) { >@@ -953,12 +962,13 @@ > > if (one_process) { > AP_MONCONTROL(1); >+ bucket[0] = 0; > make_child(ap_server_conf, 0); > /* NOTREACHED */ > } > else { >- if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */ >- ap_daemons_max_free = ap_daemons_min_free + 1; >+ if (ap_daemons_max_free < ap_daemons_min_free + num_buckets) /* Don't thrash... */ >+ ap_daemons_max_free = ap_daemons_min_free + num_buckets; > > /* If we're doing a graceful_restart then we're going to see a lot > * of children exiting immediately when we get into the main loop >@@ -991,7 +1001,7 @@ > ap_log_command_line(plog, s); > ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00165) > "Accept mutex: %s (default: %s)", >- apr_proc_mutex_name(accept_mutex), >+ apr_proc_mutex_name(accept_mutex[0]), > apr_proc_mutex_defname()); > > mpm_state = AP_MPMQ_RUNNING; >@@ -1041,7 +1051,7 @@ > /* child detected a resource shortage (E[NM]FILE, ENOBUFS, etc) > * cut the fork rate to the minimum > */ >- retained->idle_spawn_rate = 1; >+ retained->idle_spawn_rate[bucket[child_slot]] = 1; > } > else if (remaining_children_to_start > && child_slot < ap_daemons_limit) { >@@ -1086,8 +1096,9 @@ > */ > continue; > } >- >- perform_idle_server_maintenance(pconf); >+ for (i = 0; i < num_buckets; i++) { >+ perform_idle_server_maintenance(pconf, i); >+ } > } > } /* one_process */ > >@@ -1248,12 +1259,22 @@ > level_flags |= APLOG_STARTUP; > } > >+ flag = 0; /* do not bind and listen to ap_listeners */ > if ((num_listensocks = ap_setup_listeners(ap_server_conf)) < 1) { > ap_log_error(APLOG_MARK, APLOG_ALERT | level_flags, 0, > (startup ? NULL : s), > "no listening sockets available, shutting down"); > return DONE; > } >+#ifdef HAVE_SO_REUSEPORT >+ num_buckets = 4; >+#else >+ if (num_listensocks > 1) { >+ num_buckets = num_listensocks; >+ num_listensocks = 1; /* partition the listener into different bucket */ >+ } >+#endif >+ ap_post_config_listeners(ap_server_conf, pconf, num_buckets); > > if ((rv = ap_mpm_pod_open(pconf, &pod))) { > ap_log_error(APLOG_MARK, APLOG_CRIT | level_flags, rv, >@@ -1292,7 +1313,10 @@ > if (!retained) { > retained = ap_retained_data_create(userdata_key, sizeof(*retained)); > retained->max_daemons_limit = -1; >- retained->idle_spawn_rate = 1; >+ int i; >+ for (i = 0; i < 1025; i++) { >+ retained->idle_spawn_rate[i] = 1; >+ } > } > ++retained->module_loads; > if (retained->module_loads == 2) { >diff -ru httpd-2.4.7/server/mpm_unix.c httpd-2.4.7.new/server/mpm_unix.c >--- httpd-2.4.7/server/mpm_unix.c 2013-11-16 14:24:53.000000000 -0500 >+++ httpd-2.4.7.new/server/mpm_unix.c 2013-12-17 11:21:28.941978245 -0500 >@@ -607,7 +607,7 @@ > * permits the MPM to skip the poll when there is only one listening > * socket, because it provides a alternate way to unblock an accept() > * when the pod is used. */ >-static apr_status_t dummy_connection(ap_pod_t *pod) >+static apr_status_t dummy_connection(ap_pod_t *pod, ap_listen_rec *lr) > { > const char *data; > apr_status_t rv; >@@ -626,12 +626,12 @@ > * plain-HTTP, not SSL; using an SSL port would either be > * expensive to do correctly (performing a complete SSL handshake) > * or cause log spam by doing incorrectly (simply sending EOF). */ >- lp = ap_listeners; >+ lp = lr; > while (lp && lp->protocol && strcasecmp(lp->protocol, "http") != 0) { > lp = lp->next; > } > if (!lp) { >- lp = ap_listeners; >+ lp = lr; > } > > rv = apr_socket_create(&sock, lp->bind_addr->family, SOCK_STREAM, 0, p); >@@ -715,18 +715,26 @@ > AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t *pod) > { > apr_status_t rv; >+ int i; > > rv = pod_signal_internal(pod); > if (rv != APR_SUCCESS) { > return rv; > } >- >- return dummy_connection(pod); >+ >+ for (i = 0; i < num_buckets; i++) { >+ rv = dummy_connection(pod, mpm_listen[i]); >+ if (rv != APR_SUCCESS) { >+ return rv; >+ } >+ } >+ return APR_SUCCESS; > } > > void ap_mpm_pod_killpg(ap_pod_t *pod, int num) > { > int i; >+ int j; > apr_status_t rv = APR_SUCCESS; > > /* we don't write anything to the pod here... we assume >@@ -742,8 +750,11 @@ > * readers stranded (a number of them could be tied up for > * a while serving time-consuming requests) > */ >+ > for (i = 0; i < num && rv == APR_SUCCESS; i++) { >- rv = dummy_connection(pod); >+ for (j = 0; j < num_buckets; j++) { >+ rv = dummy_connection(pod, mpm_listen[j]); >+ } > } > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 55897
:
31124
|
31125
|
31126
|
31127
|
31171
|
31253
|
31397
|
31616
|
31632
|
31681
|
32079
|
32081
|
32082