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

(-)server/mpm/event/event.c (-35 / +94 lines)
Lines 160-174 Link Here
160
#endif
160
#endif
161
#define WORKER_FACTOR_SCALE   16  /* scale factor to allow fractional values */
161
#define WORKER_FACTOR_SCALE   16  /* scale factor to allow fractional values */
162
static unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE;
162
static unsigned int worker_factor = DEFAULT_WORKER_FACTOR * WORKER_FACTOR_SCALE;
163
    /* AsyncRequestWorkerFactor * 16 */
163
164
164
static int threads_per_child = 0;   /* Worker threads per child */
165
static int threads_per_child = 0;           /* ThreadsPerChild */
165
static int ap_daemons_to_start = 0;
166
static int ap_daemons_to_start = 0;         /* StartServers */
166
static int min_spare_threads = 0;
167
static int min_spare_threads = 0;           /* MinSpareThreads */
167
static int max_spare_threads = 0;
168
static int max_spare_threads = 0;           /* MaxSpareThreads */
168
static int ap_daemons_limit = 0;
169
static int ap_daemons_limit = 0;            /* MaxRequestWorkers / ThreadsPerChild */
169
static int max_workers = 0;
170
static int max_workers = 0;                 /* MaxRequestWorkers */
170
static int server_limit = 0;
171
static int server_limit = 0;                /* ServerLimit */
171
static int thread_limit = 0;
172
static int thread_limit = 0;                /* ThreadLimit */
173
static int sb_max_daemon_idx = 0;
172
static int had_healthy_child = 0;
174
static int had_healthy_child = 0;
173
static int dying = 0;
175
static int dying = 0;
174
static int workers_may_exit = 0;
176
static int workers_may_exit = 0;
Lines 181-186 Link Here
181
static apr_uint32_t lingering_count = 0;    /* Number of connections in lingering close */
183
static apr_uint32_t lingering_count = 0;    /* Number of connections in lingering close */
182
static apr_uint32_t suspended_count = 0;    /* Number of suspended connections */
184
static apr_uint32_t suspended_count = 0;    /* Number of suspended connections */
183
static apr_uint32_t clogged_count = 0;      /* Number of threads processing ssl conns */
185
static apr_uint32_t clogged_count = 0;      /* Number of threads processing ssl conns */
186
static apr_uint32_t threads_shutdown = 0;   /* Number of threads that have shutdown
187
                                               early during graceful termination */
184
static int resource_shortage = 0;
188
static int resource_shortage = 0;
185
static fd_queue_t *worker_queue;
189
static fd_queue_t *worker_queue;
186
static fd_queue_info_t *worker_queue_info;
190
static fd_queue_info_t *worker_queue_info;
Lines 288-296 Link Here
288
/* The structure used to pass unique initialization info to each thread */
292
/* The structure used to pass unique initialization info to each thread */
289
typedef struct
293
typedef struct
290
{
294
{
291
    int pid;
295
    int pslot;  /* process slot */
292
    int tid;
296
    int tslot;  /* worker slot of the thread */
293
    int sd;
294
} proc_info;
297
} proc_info;
295
298
296
/* Structure used to pass information to the thread responsible for
299
/* Structure used to pass information to the thread responsible for
Lines 911-916 Link Here
911
        || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) {
914
        || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) {
912
        apr_socket_close(csd);
915
        apr_socket_close(csd);
913
        ap_push_pool(worker_queue_info, cs->p);
916
        ap_push_pool(worker_queue_info, cs->p);
917
        if (dying)
918
            ap_queue_interrupt_one(worker_queue);
914
        return 0;
919
        return 0;
915
    }
920
    }
916
    return start_lingering_close_common(cs, 0);
921
    return start_lingering_close_common(cs, 0);
Lines 934-939 Link Here
934
        AP_DEBUG_ASSERT(0);
939
        AP_DEBUG_ASSERT(0);
935
    }
940
    }
936
    ap_push_pool(worker_queue_info, cs->p);
941
    ap_push_pool(worker_queue_info, cs->p);
942
    if (dying)
943
        ap_queue_interrupt_one(worker_queue);
937
    return 0;
944
    return 0;
938
}
945
}
939
946
Lines 1208-1213 Link Here
1208
{
1215
{
1209
    if (!*closed) {
1216
    if (!*closed) {
1210
        int i;
1217
        int i;
1218
        worker_score *ws;
1211
        disable_listensocks(process_slot);
1219
        disable_listensocks(process_slot);
1212
        ap_close_listeners_ex(my_bucket->listeners);
1220
        ap_close_listeners_ex(my_bucket->listeners);
1213
        *closed = 1;
1221
        *closed = 1;
Lines 1214-1224 Link Here
1214
        dying = 1;
1222
        dying = 1;
1215
        ap_scoreboard_image->parent[process_slot].quiescing = 1;
1223
        ap_scoreboard_image->parent[process_slot].quiescing = 1;
1216
        for (i = 0; i < threads_per_child; ++i) {
1224
        for (i = 0; i < threads_per_child; ++i) {
1225
            ws = ap_get_scoreboard_worker_from_indexes(process_slot, i);
1226
            if (ws->pid != ap_my_pid) {
1227
                /* scoreboard slot still in use by previous generation */
1228
                continue;
1229
            }
1217
            ap_update_child_status_from_indexes(process_slot, i,
1230
            ap_update_child_status_from_indexes(process_slot, i,
1218
                                                SERVER_GRACEFUL, NULL);
1231
                                                SERVER_GRACEFUL, NULL);
1219
        }
1232
        }
1220
        /* wake up the main thread */
1233
        /* wake up the main thread */
1221
        kill(ap_my_pid, SIGTERM);
1234
        kill(ap_my_pid, SIGTERM);
1235
1236
        ap_free_idle_pools(worker_queue_info);
1237
        ap_queue_interrupt_all(worker_queue);
1222
    }
1238
    }
1223
}
1239
}
1224
1240
Lines 1439-1444 Link Here
1439
    TO_QUEUE_ELEM_INIT(cs);
1455
    TO_QUEUE_ELEM_INIT(cs);
1440
1456
1441
    ap_push_pool(worker_queue_info, cs->p);
1457
    ap_push_pool(worker_queue_info, cs->p);
1458
    if (dying)
1459
        ap_queue_interrupt_one(worker_queue);
1442
}
1460
}
1443
1461
1444
/* call 'func' for all elements of 'q' with timeout less than 'timeout_time'.
1462
/* call 'func' for all elements of 'q' with timeout less than 'timeout_time'.
Lines 1518-1524 Link Here
1518
    timer_event_t *te;
1536
    timer_event_t *te;
1519
    apr_status_t rc;
1537
    apr_status_t rc;
1520
    proc_info *ti = dummy;
1538
    proc_info *ti = dummy;
1521
    int process_slot = ti->pid;
1539
    int process_slot = ti->pslot;
1522
    apr_pool_t *tpool = apr_thread_pool_get(thd);
1540
    apr_pool_t *tpool = apr_thread_pool_get(thd);
1523
    void *csd = NULL;
1541
    void *csd = NULL;
1524
    apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
1542
    apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
Lines 1584-1589 Link Here
1584
                             *keepalive_q->total,
1602
                             *keepalive_q->total,
1585
                             apr_atomic_read32(&lingering_count),
1603
                             apr_atomic_read32(&lingering_count),
1586
                             apr_atomic_read32(&suspended_count));
1604
                             apr_atomic_read32(&suspended_count));
1605
                if (dying) {
1606
                    ap_log_error(APLOG_MARK, APLOG_TRACE6, 0, ap_server_conf,
1607
                                 "%u/%u workers shutdown",
1608
                                 apr_atomic_read32(&threads_shutdown),
1609
                                 threads_per_child);
1610
                }
1587
                apr_thread_mutex_unlock(timeout_mutex);
1611
                apr_thread_mutex_unlock(timeout_mutex);
1588
            }
1612
            }
1589
        }
1613
        }
Lines 1818-1828 Link Here
1818
            /* If all workers are busy, we kill older keep-alive connections so that they
1842
            /* If all workers are busy, we kill older keep-alive connections so that they
1819
             * may connect to another process.
1843
             * may connect to another process.
1820
             */
1844
             */
1821
            if (workers_were_busy && *keepalive_q->total) {
1845
            if ((workers_were_busy || dying) && *keepalive_q->total) {
1822
                ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1846
                if (!dying)
1823
                             "All workers are busy, will close %d keep-alive "
1847
                    ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
1824
                             "connections",
1848
                                 "All workers are busy, will close %d keep-alive "
1825
                             *keepalive_q->total);
1849
                                 "connections",
1850
                                 *keepalive_q->total);
1826
                process_timeout_queue(keepalive_q, 0,
1851
                process_timeout_queue(keepalive_q, 0,
1827
                                      start_lingering_close_nonblocking);
1852
                                      start_lingering_close_nonblocking);
1828
            }
1853
            }
Lines 1869-1874 Link Here
1869
    return NULL;
1894
    return NULL;
1870
}
1895
}
1871
1896
1897
/*
1898
 * During graceful shutdown, if there are more running worker threads than
1899
 * open connections, exit one worker thread.
1900
 *
1901
 * return 1 if thread should exit, 0 if it should continue running.
1902
 */
1903
static int worker_thread_should_exit_early(void)
1904
{
1905
    for (;;) {
1906
        apr_uint32_t conns = apr_atomic_read32(&connection_count);
1907
        apr_uint32_t dead = apr_atomic_read32(&threads_shutdown);
1908
        apr_uint32_t newdead;
1909
1910
        AP_DEBUG_ASSERT(dead <= threads_per_child);
1911
        if (conns >= threads_per_child - dead)
1912
            return 0;
1913
1914
        newdead = dead + 1;
1915
        if (apr_atomic_cas32(&threads_shutdown, newdead, dead) == dead) {
1916
            /*
1917
             * No other thread has exited in the mean time, safe to exit
1918
             * this one.
1919
             */
1920
            return 1;
1921
        }
1922
    }
1923
}
1924
1872
/* XXX For ungraceful termination/restart, we definitely don't want to
1925
/* XXX For ungraceful termination/restart, we definitely don't want to
1873
 *     wait for active connections to finish but we may want to wait
1926
 *     wait for active connections to finish but we may want to wait
1874
 *     for idle workers to get out of the queue code and release mutexes,
1927
 *     for idle workers to get out of the queue code and release mutexes,
Lines 1879-1886 Link Here
1879
static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1932
static void *APR_THREAD_FUNC worker_thread(apr_thread_t * thd, void *dummy)
1880
{
1933
{
1881
    proc_info *ti = dummy;
1934
    proc_info *ti = dummy;
1882
    int process_slot = ti->pid;
1935
    int process_slot = ti->pslot;
1883
    int thread_slot = ti->tid;
1936
    int thread_slot = ti->tslot;
1884
    apr_socket_t *csd = NULL;
1937
    apr_socket_t *csd = NULL;
1885
    event_conn_state_t *cs;
1938
    event_conn_state_t *cs;
1886
    apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
1939
    apr_pool_t *ptrans;         /* Pool for per-transaction stuff */
Lines 1915-1920 Link Here
1915
        if (workers_may_exit) {
1968
        if (workers_may_exit) {
1916
            break;
1969
            break;
1917
        }
1970
        }
1971
        if (dying && worker_thread_should_exit_early()) {
1972
            break;
1973
        }
1918
1974
1919
        te = NULL;
1975
        te = NULL;
1920
        rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
1976
        rv = ap_queue_pop_something(worker_queue, &csd, &cs, &ptrans, &te);
Lines 1993-2001 Link Here
1993
    apr_status_t rv;
2049
    apr_status_t rv;
1994
2050
1995
    my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2051
    my_info = (proc_info *) ap_malloc(sizeof(proc_info));
1996
    my_info->pid = my_child_num;
2052
    my_info->pslot = my_child_num;
1997
    my_info->tid = -1;          /* listener thread doesn't have a thread slot */
2053
    my_info->tslot = -1;      /* listener thread doesn't have a thread slot */
1998
    my_info->sd = 0;
1999
    rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
2054
    rv = apr_thread_create(&ts->listener, thread_attr, listener_thread,
2000
                           my_info, pchild);
2055
                           my_info, pchild);
2001
    if (rv != APR_SUCCESS) {
2056
    if (rv != APR_SUCCESS) {
Lines 2104-2117 Link Here
2104
            int status =
2159
            int status =
2105
                ap_scoreboard_image->servers[child_num_arg][i].status;
2160
                ap_scoreboard_image->servers[child_num_arg][i].status;
2106
2161
2107
            if (status != SERVER_GRACEFUL && status != SERVER_DEAD) {
2162
            if (status != SERVER_DEAD) {
2108
                continue;
2163
                continue;
2109
            }
2164
            }
2110
2165
2111
            my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2166
            my_info = (proc_info *) ap_malloc(sizeof(proc_info));
2112
            my_info->pid = my_child_num;
2167
            my_info->pslot = my_child_num;
2113
            my_info->tid = i;
2168
            my_info->tslot = i;
2114
            my_info->sd = 0;
2115
2169
2116
            /* We are creating threads right now */
2170
            /* We are creating threads right now */
2117
            ap_update_child_status_from_indexes(my_child_num, i,
2171
            ap_update_child_status_from_indexes(my_child_num, i,
Lines 2484-2490 Link Here
2484
{
2538
{
2485
    int i;
2539
    int i;
2486
2540
2487
    for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
2541
    for (i = 0; number_to_start && i < sb_max_daemon_idx; ++i) {
2488
        if (ap_scoreboard_image->parent[i].pid != 0) {
2542
        if (ap_scoreboard_image->parent[i].pid != 0) {
2489
            continue;
2543
            continue;
2490
        }
2544
        }
Lines 2515-2521 Link Here
2515
    last_non_dead = -1;
2569
    last_non_dead = -1;
2516
    total_non_dead = 0;
2570
    total_non_dead = 0;
2517
2571
2518
    for (i = 0; i < ap_daemons_limit; ++i) {
2572
    for (i = 0; i < sb_max_daemon_idx; ++i) {
2519
        /* Initialization to satisfy the compiler. It doesn't know
2573
        /* Initialization to satisfy the compiler. It doesn't know
2520
         * that threads_per_child is always > 0 */
2574
         * that threads_per_child is always > 0 */
2521
        int status = SERVER_DEAD;
2575
        int status = SERVER_DEAD;
Lines 2739-2745 Link Here
2739
                    retained->idle_spawn_rate[ps->bucket] = 1;
2793
                    retained->idle_spawn_rate[ps->bucket] = 1;
2740
                }
2794
                }
2741
                else if (remaining_children_to_start
2795
                else if (remaining_children_to_start
2742
                         && child_slot < ap_daemons_limit) {
2796
                         && child_slot < sb_max_daemon_idx) {
2743
                    /* we're still doing a 1-for-1 replacement of dead
2797
                    /* we're still doing a 1-for-1 replacement of dead
2744
                     * children with new children
2798
                     * children with new children
2745
                     */
2799
                     */
Lines 2835-2840 Link Here
2835
    if (max_spare_threads < min_spare_threads + threads_per_child * num_buckets)
2889
    if (max_spare_threads < min_spare_threads + threads_per_child * num_buckets)
2836
        max_spare_threads = min_spare_threads + threads_per_child * num_buckets;
2890
        max_spare_threads = min_spare_threads + threads_per_child * num_buckets;
2837
2891
2892
    sb_max_daemon_idx = 10 * ap_daemons_limit;
2893
    if (sb_max_daemon_idx > server_limit) {
2894
        sb_max_daemon_idx = server_limit;
2895
    }
2838
    /* If we're doing a graceful_restart then we're going to see a lot
2896
    /* If we're doing a graceful_restart then we're going to see a lot
2839
     * of children exiting immediately when we get into the main loop
2897
     * of children exiting immediately when we get into the main loop
2840
     * below (because we just sent them AP_SIG_GRACEFUL).  This happens pretty
2898
     * below (because we just sent them AP_SIG_GRACEFUL).  This happens pretty
Lines 2876-2882 Link Here
2876
         * Kill child processes, tell them to call child_exit, etc...
2934
         * Kill child processes, tell them to call child_exit, etc...
2877
         */
2935
         */
2878
        for (i = 0; i < num_buckets; i++) {
2936
        for (i = 0; i < num_buckets; i++) {
2879
            ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
2937
            ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx,
2880
                               AP_MPM_PODX_RESTART);
2938
                               AP_MPM_PODX_RESTART);
2881
        }
2939
        }
2882
        ap_reclaim_child_processes(1, /* Start with SIGTERM */
2940
        ap_reclaim_child_processes(1, /* Start with SIGTERM */
Lines 2900-2906 Link Here
2900
        /* Close our listeners, and then ask our children to do same */
2958
        /* Close our listeners, and then ask our children to do same */
2901
        ap_close_listeners();
2959
        ap_close_listeners();
2902
        for (i = 0; i < num_buckets; i++) {
2960
        for (i = 0; i < num_buckets; i++) {
2903
            ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
2961
            ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx,
2904
                               AP_MPM_PODX_GRACEFUL);
2962
                               AP_MPM_PODX_GRACEFUL);
2905
        }
2963
        }
2906
        ap_relieve_child_processes(event_note_child_killed);
2964
        ap_relieve_child_processes(event_note_child_killed);
Lines 2928-2934 Link Here
2928
            ap_relieve_child_processes(event_note_child_killed);
2986
            ap_relieve_child_processes(event_note_child_killed);
2929
2987
2930
            active_children = 0;
2988
            active_children = 0;
2931
            for (index = 0; index < ap_daemons_limit; ++index) {
2989
            for (index = 0; index < sb_max_daemon_idx; ++index) {
2932
                if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
2990
                if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
2933
                    active_children = 1;
2991
                    active_children = 1;
2934
                    /* Having just one child is enough to stay around */
2992
                    /* Having just one child is enough to stay around */
Lines 2943-2949 Link Here
2943
         * really dead.
3001
         * really dead.
2944
         */
3002
         */
2945
        for (i = 0; i < num_buckets; i++) {
3003
        for (i = 0; i < num_buckets; i++) {
2946
            ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
3004
            ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx,
2947
                               AP_MPM_PODX_RESTART);
3005
                               AP_MPM_PODX_RESTART);
2948
        }
3006
        }
2949
        ap_reclaim_child_processes(1, event_note_child_killed);
3007
        ap_reclaim_child_processes(1, event_note_child_killed);
Lines 2972-2978 Link Here
2972
                     " received.  Doing graceful restart");
3030
                     " received.  Doing graceful restart");
2973
        /* wake up the children...time to die.  But we'll have more soon */
3031
        /* wake up the children...time to die.  But we'll have more soon */
2974
        for (i = 0; i < num_buckets; i++) {
3032
        for (i = 0; i < num_buckets; i++) {
2975
            ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
3033
            ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx,
2976
                               AP_MPM_PODX_GRACEFUL);
3034
                               AP_MPM_PODX_GRACEFUL);
2977
        }
3035
        }
2978
3036
Lines 2987-2993 Link Here
2987
         * pthreads are stealing signals from us left and right.
3045
         * pthreads are stealing signals from us left and right.
2988
         */
3046
         */
2989
        for (i = 0; i < num_buckets; i++) {
3047
        for (i = 0; i < num_buckets; i++) {
2990
            ap_mpm_podx_killpg(all_buckets[i].pod, ap_daemons_limit,
3048
            ap_mpm_podx_killpg(all_buckets[i].pod, sb_max_daemon_idx,
2991
                               AP_MPM_PODX_RESTART);
3049
                               AP_MPM_PODX_RESTART);
2992
        }
3050
        }
2993
3051
Lines 3211-3216 Link Here
3211
    server_limit = DEFAULT_SERVER_LIMIT;
3269
    server_limit = DEFAULT_SERVER_LIMIT;
3212
    thread_limit = DEFAULT_THREAD_LIMIT;
3270
    thread_limit = DEFAULT_THREAD_LIMIT;
3213
    ap_daemons_limit = server_limit;
3271
    ap_daemons_limit = server_limit;
3272
    sb_max_daemon_idx = server_limit;
3214
    threads_per_child = DEFAULT_THREADS_PER_CHILD;
3273
    threads_per_child = DEFAULT_THREADS_PER_CHILD;
3215
    max_workers = ap_daemons_limit * threads_per_child;
3274
    max_workers = ap_daemons_limit * threads_per_child;
3216
    had_healthy_child = 0;
3275
    had_healthy_child = 0;
(-)server/mpm/event/fdqueue.c (-16 / +36 lines)
Lines 280-285 Link Here
280
    }
280
    }
281
}
281
}
282
282
283
void ap_free_idle_pools(fd_queue_info_t *queue_info)
284
{
285
    apr_pool_t *p;
286
287
    queue_info->max_recycled_pools = 0;
288
    do {
289
        ap_pop_pool(&p, queue_info);
290
        if (p != NULL)
291
            apr_pool_destroy(p);
292
    } while (p != NULL);
293
}
294
295
283
apr_status_t ap_queue_info_term(fd_queue_info_t * queue_info)
296
apr_status_t ap_queue_info_term(fd_queue_info_t * queue_info)
284
{
297
{
285
    apr_status_t rv;
298
    apr_status_t rv;
Lines 477-483 Link Here
477
    return rv;
490
    return rv;
478
}
491
}
479
492
480
apr_status_t ap_queue_interrupt_all(fd_queue_t * queue)
493
static apr_status_t queue_interrupt(fd_queue_t *queue, int all, int term)
481
{
494
{
482
    apr_status_t rv;
495
    apr_status_t rv;
483
496
Lines 484-507 Link Here
484
    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
497
    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
485
        return rv;
498
        return rv;
486
    }
499
    }
487
    apr_thread_cond_broadcast(queue->not_empty);
488
    return apr_thread_mutex_unlock(queue->one_big_mutex);
489
}
490
491
apr_status_t ap_queue_term(fd_queue_t * queue)
492
{
493
    apr_status_t rv;
494
495
    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
496
        return rv;
497
    }
498
    /* we must hold one_big_mutex when setting this... otherwise,
500
    /* we must hold one_big_mutex when setting this... otherwise,
499
     * we could end up setting it and waking everybody up just after a
501
     * we could end up setting it and waking everybody up just after a
500
     * would-be popper checks it but right before they block
502
     * would-be popper checks it but right before they block
501
     */
503
     */
502
    queue->terminated = 1;
504
    if (term) {
503
    if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
505
        queue->terminated = 1;
504
        return rv;
505
    }
506
    }
506
    return ap_queue_interrupt_all(queue);
507
    if (all)
508
        apr_thread_cond_broadcast(queue->not_empty);
509
    else
510
        apr_thread_cond_signal(queue->not_empty);
511
    return apr_thread_mutex_unlock(queue->one_big_mutex);
507
}
512
}
513
514
apr_status_t ap_queue_interrupt_all(fd_queue_t * queue)
515
{
516
    return queue_interrupt(queue, 1, 0);
517
}
518
519
apr_status_t ap_queue_interrupt_one(fd_queue_t * queue)
520
{
521
    return queue_interrupt(queue, 0, 0);
522
}
523
524
apr_status_t ap_queue_term(fd_queue_t * queue)
525
{
526
    return queue_interrupt(queue, 1, 1);
527
}
(-)server/mpm/event/fdqueue.h (+2 lines)
Lines 52-57 Link Here
52
                                          int *had_to_block);
52
                                          int *had_to_block);
53
apr_status_t ap_queue_info_term(fd_queue_info_t * queue_info);
53
apr_status_t ap_queue_info_term(fd_queue_info_t * queue_info);
54
apr_uint32_t ap_queue_info_get_idlers(fd_queue_info_t * queue_info);
54
apr_uint32_t ap_queue_info_get_idlers(fd_queue_info_t * queue_info);
55
void ap_free_idle_pools(fd_queue_info_t *queue_info);
55
56
56
struct fd_queue_elem_t
57
struct fd_queue_elem_t
57
{
58
{
Lines 98-103 Link Here
98
                                    event_conn_state_t ** ecs, apr_pool_t ** p,
99
                                    event_conn_state_t ** ecs, apr_pool_t ** p,
99
                                    timer_event_t ** te);
100
                                    timer_event_t ** te);
100
apr_status_t ap_queue_interrupt_all(fd_queue_t * queue);
101
apr_status_t ap_queue_interrupt_all(fd_queue_t * queue);
102
apr_status_t ap_queue_interrupt_one(fd_queue_t * queue);
101
apr_status_t ap_queue_term(fd_queue_t * queue);
103
apr_status_t ap_queue_term(fd_queue_t * queue);
102
104
103
#endif /* FDQUEUE_H */
105
#endif /* FDQUEUE_H */
(-)server/mpm/worker/fdqueue.c (-15 / +14 lines)
Lines 382-388 Link Here
382
    return rv;
382
    return rv;
383
}
383
}
384
384
385
apr_status_t ap_queue_interrupt_all(fd_queue_t *queue)
385
static apr_status_t queue_interrupt_all(fd_queue_t *queue, int term)
386
{
386
{
387
    apr_status_t rv;
387
    apr_status_t rv;
388
388
Lines 389-412 Link Here
389
    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
389
    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
390
        return rv;
390
        return rv;
391
    }
391
    }
392
    /* we must hold one_big_mutex when setting this... otherwise,
393
     * we could end up setting it and waking everybody up just after a
394
     * would-be popper checks it but right before they block
395
     */
396
    if (term) {
397
        queue->terminated = 1;
398
    }
392
    apr_thread_cond_broadcast(queue->not_empty);
399
    apr_thread_cond_broadcast(queue->not_empty);
393
    return apr_thread_mutex_unlock(queue->one_big_mutex);
400
    return apr_thread_mutex_unlock(queue->one_big_mutex);
394
}
401
}
395
402
403
apr_status_t ap_queue_interrupt_all(fd_queue_t *queue)
404
{
405
    return queue_interrupt_all(queue, 0);
406
}
407
396
apr_status_t ap_queue_term(fd_queue_t *queue)
408
apr_status_t ap_queue_term(fd_queue_t *queue)
397
{
409
{
398
    apr_status_t rv;
410
    return queue_interrupt_all(queue, 1);
399
400
    if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
401
        return rv;
402
    }
403
    /* we must hold one_big_mutex when setting this... otherwise,
404
     * we could end up setting it and waking everybody up just after a
405
     * would-be popper checks it but right before they block
406
     */
407
    queue->terminated = 1;
408
    if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
409
        return rv;
410
    }
411
    return ap_queue_interrupt_all(queue);
412
}
411
}
(-)server/scoreboard.c (-1 / +1 lines)
Lines 399-405 Link Here
399
    int i;
399
    int i;
400
    int max_daemons_limit = 0;
400
    int max_daemons_limit = 0;
401
401
402
    ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_daemons_limit);
402
    ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &max_daemons_limit);
403
403
404
    for (i = 0; i < max_daemons_limit; ++i) {
404
    for (i = 0; i < max_daemons_limit; ++i) {
405
        if (ap_scoreboard_image->parent[i].pid == pid->pid) {
405
        if (ap_scoreboard_image->parent[i].pid == pid->pid) {

Return to bug 53555