View | Details | Raw Unified | Return to bug 61979
Collapse All | Expand All

(-)server/mpm/event/event.c (-33 / +47 lines)
Lines 184-190 static volatile int dying = 0; Link Here
184
static volatile int workers_may_exit = 0;
184
static volatile int workers_may_exit = 0;
185
static volatile int start_thread_may_exit = 0;
185
static volatile int start_thread_may_exit = 0;
186
static volatile int listener_may_exit = 0;
186
static volatile int listener_may_exit = 0;
187
static volatile int listeners_disabled = 0;
188
static int listener_is_wakeable = 0;        /* Pollset supports APR_POLLSET_WAKEABLE */
187
static int listener_is_wakeable = 0;        /* Pollset supports APR_POLLSET_WAKEABLE */
189
static int num_listensocks = 0;
188
static int num_listensocks = 0;
190
static apr_int32_t conns_this_child;        /* MaxConnectionsPerChild, only access
189
static apr_int32_t conns_this_child;        /* MaxConnectionsPerChild, only access
Lines 470-475 static pid_t ap_my_pid; /* Linux getpid() Link Here
470
static pid_t parent_pid;
469
static pid_t parent_pid;
471
static apr_os_thread_t *listener_os_thread;
470
static apr_os_thread_t *listener_os_thread;
472
471
472
static int ap_child_slot;       /* Current child process slot in scoreboard */
473
473
/* The LISTENER_SIGNAL signal will be sent from the main thread to the
474
/* The LISTENER_SIGNAL signal will be sent from the main thread to the
474
 * listener thread to wake it up for graceful termination (what a child
475
 * listener thread to wake it up for graceful termination (what a child
475
 * process from an old generation does when the admin does "apachectl
476
 * process from an old generation does when the admin does "apachectl
Lines 483-505 static apr_os_thread_t *listener_os_thread; Link Here
483
 */
484
 */
484
static apr_socket_t **worker_sockets;
485
static apr_socket_t **worker_sockets;
485
486
486
static void disable_listensocks(int process_slot)
487
static volatile apr_uint32_t listensocks_disabled;
488
489
static void disable_listensocks(void)
487
{
490
{
488
    int i;
491
    int i;
489
    listeners_disabled = 1;
492
    if (apr_atomic_cas32(&listensocks_disabled, 1, 0) != 0) {
490
    for (i = 0; i < num_listensocks; i++) {
493
        return;
491
        apr_pollset_remove(event_pollset, &listener_pollfd[i]);
492
    }
494
    }
493
    ap_scoreboard_image->parent[process_slot].not_accepting = 1;
495
    if (event_pollset) {
496
        for (i = 0; i < num_listensocks; i++) {
497
            apr_pollset_remove(event_pollset, &listener_pollfd[i]);
498
        }
499
    }
500
    ap_scoreboard_image->parent[ap_child_slot].not_accepting = 1;
494
}
501
}
495
502
496
static void enable_listensocks(int process_slot)
503
static void enable_listensocks(void)
497
{
504
{
498
    int i;
505
    int i;
499
    if (listener_may_exit) {
506
    if (listener_may_exit
507
            || apr_atomic_cas32(&listensocks_disabled, 0, 1) != 1) {
500
        return;
508
        return;
501
    }
509
    }
502
    listeners_disabled = 0;
503
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457)
510
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00457)
504
                 "Accepting new connections again: "
511
                 "Accepting new connections again: "
505
                 "%u active conns (%u lingering/%u clogged/%u suspended), "
512
                 "%u active conns (%u lingering/%u clogged/%u suspended), "
Lines 515-523 static apr_socket_t **worker_sockets; Link Here
515
     * XXX: This is not yet optimal. If many workers suddenly become available,
522
     * XXX: This is not yet optimal. If many workers suddenly become available,
516
     * XXX: the parent may kill some processes off too soon.
523
     * XXX: the parent may kill some processes off too soon.
517
     */
524
     */
518
    ap_scoreboard_image->parent[process_slot].not_accepting = 0;
525
    ap_scoreboard_image->parent[ap_child_slot].not_accepting = 0;
519
}
526
}
520
527
528
static APR_INLINE apr_uint32_t listeners_disabled(void)
529
{
530
    return apr_atomic_read32(&listensocks_disabled);
531
}
532
521
static APR_INLINE int connections_above_limit(void)
533
static APR_INLINE int connections_above_limit(void)
522
{
534
{
523
    apr_uint32_t i_count = ap_queue_info_get_idlers(worker_queue_info);
535
    apr_uint32_t i_count = ap_queue_info_get_idlers(worker_queue_info);
Lines 525-533 static APR_INLINE int connections_above_limit(void Link Here
525
        apr_uint32_t c_count = apr_atomic_read32(&connection_count);
537
        apr_uint32_t c_count = apr_atomic_read32(&connection_count);
526
        apr_uint32_t l_count = apr_atomic_read32(&lingering_count);
538
        apr_uint32_t l_count = apr_atomic_read32(&lingering_count);
527
        if (c_count <= l_count
539
        if (c_count <= l_count
528
                /* Off by 'listeners_disabled' to avoid flip flop */
540
                /* Off by 'listeners_disabled()' to avoid flip flop */
529
                || c_count - l_count < (apr_uint32_t)threads_per_child +
541
                || c_count - l_count < (apr_uint32_t)threads_per_child +
530
                                       (i_count - (listeners_disabled != 0)) *
542
                                       (i_count - listeners_disabled()) *
531
                                       (worker_factor / WORKER_FACTOR_SCALE)) {
543
                                       (worker_factor / WORKER_FACTOR_SCALE)) {
532
            return 0;
544
            return 0;
533
        }
545
        }
Lines 590-595 static void close_worker_sockets(void) Link Here
590
static void wakeup_listener(void)
602
static void wakeup_listener(void)
591
{
603
{
592
    listener_may_exit = 1;
604
    listener_may_exit = 1;
605
    disable_listensocks();
593
606
594
    /* Unblock the listener if it's poll()ing */
607
    /* Unblock the listener if it's poll()ing */
595
    if (event_pollset && listener_is_wakeable) {
608
    if (event_pollset && listener_is_wakeable) {
Lines 793-799 static apr_status_t decrement_connection_count(voi Link Here
793
    is_last_connection = !apr_atomic_dec32(&connection_count);
806
    is_last_connection = !apr_atomic_dec32(&connection_count);
794
    if (listener_is_wakeable
807
    if (listener_is_wakeable
795
            && ((is_last_connection && listener_may_exit)
808
            && ((is_last_connection && listener_may_exit)
796
                || (listeners_disabled && !connections_above_limit()))) {
809
                || (listeners_disabled() && !connections_above_limit()))) {
797
        apr_pollset_wakeup(event_pollset);
810
        apr_pollset_wakeup(event_pollset);
798
    }
811
    }
799
    return APR_SUCCESS;
812
    return APR_SUCCESS;
Lines 1270-1286 static void check_infinite_requests(void) Link Here
1270
    }
1283
    }
1271
}
1284
}
1272
1285
1273
static void close_listeners(int process_slot, int *closed)
1286
static void close_listeners(int *closed)
1274
{
1287
{
1275
    if (!*closed) {
1288
    if (!*closed) {
1276
        int i;
1289
        int i;
1277
        disable_listensocks(process_slot);
1278
        ap_close_listeners_ex(my_bucket->listeners);
1290
        ap_close_listeners_ex(my_bucket->listeners);
1279
        *closed = 1;
1291
        *closed = 1;
1280
        dying = 1;
1292
        dying = 1;
1281
        ap_scoreboard_image->parent[process_slot].quiescing = 1;
1293
        ap_scoreboard_image->parent[ap_child_slot].quiescing = 1;
1282
        for (i = 0; i < threads_per_child; ++i) {
1294
        for (i = 0; i < threads_per_child; ++i) {
1283
            ap_update_child_status_from_indexes(process_slot, i,
1295
            ap_update_child_status_from_indexes(ap_child_slot, i,
1284
                                                SERVER_GRACEFUL, NULL);
1296
                                                SERVER_GRACEFUL, NULL);
1285
        }
1297
        }
1286
        /* wake up the main thread */
1298
        /* wake up the main thread */
Lines 1794-1801 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
1794
        ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1806
        ap_log_error(APLOG_MARK, APLOG_ERR, rc, ap_server_conf,
1795
                     APLOGNO(03266)
1807
                     APLOGNO(03266)
1796
                     "failed to initialize pollset, "
1808
                     "failed to initialize pollset, "
1797
                     "attempting to shutdown process gracefully");
1809
                     "shutdown process now");
1798
        signal_threads(ST_GRACEFUL);
1810
        resource_shortage = 1;
1811
        signal_threads(ST_UNGRACEFUL);
1799
        return NULL;
1812
        return NULL;
1800
    }
1813
    }
1801
1814
Lines 1817-1823 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
1817
            check_infinite_requests();
1830
            check_infinite_requests();
1818
1831
1819
        if (listener_may_exit) {
1832
        if (listener_may_exit) {
1820
            close_listeners(process_slot, &closed);
1833
            close_listeners(&closed);
1821
            if (terminate_mode == ST_UNGRACEFUL
1834
            if (terminate_mode == ST_UNGRACEFUL
1822
                || apr_atomic_read32(&connection_count) == 0)
1835
                || apr_atomic_read32(&connection_count) == 0)
1823
                break;
1836
                break;
Lines 1926-1932 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
1926
                 * need to update timeouts (logic is above, so simply restart
1939
                 * need to update timeouts (logic is above, so simply restart
1927
                 * the loop).
1940
                 * the loop).
1928
                 */
1941
                 */
1929
                if (!listener_may_exit && !listeners_disabled) {
1942
                if (!listener_may_exit && !listeners_disabled()) {
1930
                    continue;
1943
                    continue;
1931
                }
1944
                }
1932
                timeout_time = 0;
1945
                timeout_time = 0;
Lines 1942-1954 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
1942
        }
1955
        }
1943
1956
1944
        if (listener_may_exit) {
1957
        if (listener_may_exit) {
1945
            close_listeners(process_slot, &closed);
1958
            close_listeners(&closed);
1946
            if (terminate_mode == ST_UNGRACEFUL
1959
            if (terminate_mode == ST_UNGRACEFUL
1947
                || apr_atomic_read32(&connection_count) == 0)
1960
                || apr_atomic_read32(&connection_count) == 0)
1948
                break;
1961
                break;
1949
        }
1962
        }
1950
1963
1951
        while (num) {
1964
        for (; num; --num, ++out_pfd) {
1952
            listener_poll_type *pt = (listener_poll_type *) out_pfd->client_data;
1965
            listener_poll_type *pt = (listener_poll_type *) out_pfd->client_data;
1953
            if (pt->type == PT_CSD) {
1966
            if (pt->type == PT_CSD) {
1954
                /* one of the sockets is readable */
1967
                /* one of the sockets is readable */
Lines 2009-2018 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
2009
                    ap_assert(0);
2022
                    ap_assert(0);
2010
                }
2023
                }
2011
            }
2024
            }
2012
            else if (pt->type == PT_ACCEPT && !listeners_disabled) {
2025
            else if (pt->type == PT_ACCEPT && !listeners_disabled()) {
2013
                /* A Listener Socket is ready for an accept() */
2026
                /* A Listener Socket is ready for an accept() */
2014
                if (workers_were_busy) {
2027
                if (workers_were_busy) {
2015
                    disable_listensocks(process_slot);
2028
                    disable_listensocks();
2016
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
2029
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
2017
                                 APLOGNO(03268)
2030
                                 APLOGNO(03268)
2018
                                 "All workers busy, not accepting new conns "
2031
                                 "All workers busy, not accepting new conns "
Lines 2019-2025 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
2019
                                 "in this process");
2032
                                 "in this process");
2020
                }
2033
                }
2021
                else if (connections_above_limit()) {
2034
                else if (connections_above_limit()) {
2022
                    disable_listensocks(process_slot);
2035
                    disable_listensocks();
2023
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
2036
                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf,
2024
                                 APLOGNO(03269)
2037
                                 APLOGNO(03269)
2025
                                 "Too many open connections (%u), "
2038
                                 "Too many open connections (%u), "
Lines 2048-2055 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
2048
                                         ap_server_conf, APLOGNO(03097)
2061
                                         ap_server_conf, APLOGNO(03097)
2049
                                         "Failed to create transaction pool");
2062
                                         "Failed to create transaction pool");
2050
                            apr_allocator_destroy(allocator);
2063
                            apr_allocator_destroy(allocator);
2064
                            resource_shortage = 1;
2051
                            signal_threads(ST_GRACEFUL);
2065
                            signal_threads(ST_GRACEFUL);
2052
                            return NULL;
2066
                            continue;
2053
                        }
2067
                        }
2054
                        apr_allocator_owner_set(allocator, ptrans);
2068
                        apr_allocator_owner_set(allocator, ptrans);
2055
                    }
2069
                    }
Lines 2118-2126 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
2118
                    push_timer2worker(te);
2132
                    push_timer2worker(te);
2119
                }
2133
                }
2120
            }
2134
            }
2121
            out_pfd++;
2135
        } /* for processing poll */
2122
            num--;
2123
        }                   /* while for processing poll */
2124
2136
2125
        /* XXX possible optimization: stash the current time for use as
2137
        /* XXX possible optimization: stash the current time for use as
2126
         * r->request_time for new requests
2138
         * r->request_time for new requests
Lines 2192-2205 static void * APR_THREAD_FUNC listener_thread(apr_ Link Here
2192
            }
2204
            }
2193
        }
2205
        }
2194
2206
2195
        if (listeners_disabled
2207
        if (listeners_disabled()
2196
                && !workers_were_busy
2208
                && !workers_were_busy
2197
                && !connections_above_limit()) {
2209
                && !connections_above_limit()) {
2198
            enable_listensocks(process_slot);
2210
            enable_listensocks();
2199
        }
2211
        }
2200
    } /* listener main loop */
2212
    } /* listener main loop */
2201
2213
2202
    close_listeners(process_slot, &closed);
2214
    close_listeners(&closed);
2203
    ap_queue_term(worker_queue);
2215
    ap_queue_term(worker_queue);
2204
2216
2205
    apr_thread_exit(thd, APR_SUCCESS);
2217
    apr_thread_exit(thd, APR_SUCCESS);
Lines 2649-2654 static void child_main(int child_num_arg, int chil Link Here
2649
    retained->mpm->mpm_state = AP_MPMQ_STARTING;
2661
    retained->mpm->mpm_state = AP_MPMQ_STARTING;
2650
2662
2651
    ap_my_pid = getpid();
2663
    ap_my_pid = getpid();
2664
    ap_child_slot = child_num_arg;
2652
    ap_fatal_signal_child_setup(ap_server_conf);
2665
    ap_fatal_signal_child_setup(ap_server_conf);
2653
    apr_pool_create(&pchild, pconf);
2666
    apr_pool_create(&pchild, pconf);
2654
2667
Lines 3625-3630 static int event_pre_config(apr_pool_t * pconf, ap Link Here
3625
    event_pollset = NULL;
3638
    event_pollset = NULL;
3626
    worker_queue_info = NULL;
3639
    worker_queue_info = NULL;
3627
    listener_os_thread = NULL;
3640
    listener_os_thread = NULL;
3641
    listensocks_disabled = 0;
3628
3642
3629
    return OK;
3643
    return OK;
3630
}
3644
}

Return to bug 61979