child.c revision 536d2e7cd1fdec1255b8c3bdf41fdc714c506a54
97a9a944b5887e91042b019776c41d5dd74557aferikabele/* Licensed to the Apache Software Foundation (ASF) under one or more
97a9a944b5887e91042b019776c41d5dd74557aferikabele * contributor license agreements. See the NOTICE file distributed with
97a9a944b5887e91042b019776c41d5dd74557aferikabele * this work for additional information regarding copyright ownership.
8c81ebbdeed67059e7a1106d7c617543e901c3abyoshiki * The ASF licenses this file to You under the Apache License, Version 2.0
8c81ebbdeed67059e7a1106d7c617543e901c3abyoshiki * (the "License"); you may not use this file except in compliance with
8c81ebbdeed67059e7a1106d7c617543e901c3abyoshiki * the License. You may obtain a copy of the License at
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd * Unless required by applicable law or agreed to in writing, software
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * distributed under the License is distributed on an "AS IS" BASIS,
2e545ce2450a9953665f701bb05350f0d3f26275nd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * See the License for the specific language governing permissions and
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * limitations under the License.
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd#include "http_vhost.h" /* for ap_update_vhost_given_ip */
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh {0xb5367df1, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
1f1b6bf13313fdd14a45e52e553d3ff28689b717coartypedef BOOL (WINAPI *LPFN_ACCEPTEX)(SOCKET, SOCKET, PVOID, DWORD, DWORD, DWORD, LPDWORD, LPOVERLAPPED);
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd#endif /* WSAID_ACCEPTEX */
f61ec47ec494705bd2d02b5b6fe021e5c193f2c8noodl {0xb5367df2, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}}
f61ec47ec494705bd2d02b5b6fe021e5c193f2c8noodltypedef VOID (WINAPI *LPFN_GETACCEPTEXSOCKADDRS)(PVOID, DWORD, DWORD, DWORD,
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd#endif /* WSAID_GETACCEPTEXSOCKADDRS */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive#endif /* __MINGW32__ */
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * The Windows MPM uses a queue of completion contexts that it passes
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * between the accept threads and the worker threads. Declare the
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * functions to access the queue and the structures passed on the
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * queue in the header file to enable modules to access them
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * if necessary. The queue resides in the MPM.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive#define CONTAINING_RECORD(address, type, field) ((type *)( \
06ba4a61654b3763ad65f52283832ebf058fdf1cslive (char *)(address) - \
06ba4a61654b3763ad65f52283832ebf058fdf1cslive/* Queue for managing the passing of winnt_conn_ctx_t between
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * the accept and worker threads.
06ba4a61654b3763ad65f52283832ebf058fdf1cslivetypedef struct winnt_conn_ctx_t_s {
e1e8390280254f7f0580d701e583f670643d4f3fnilguntypedef enum {
e1e8390280254f7f0580d701e583f670643d4f3fnilgunstatic int workers_may_exit = 0;
e1e8390280254f7f0580d701e583f670643d4f3fnilgunstatic unsigned int g_blocked_threads = 0;
3a6531f1fd50efd78381e5800802a1449096781eslivestatic void mpm_recycle_completion_context(winnt_conn_ctx_t *context)
06ba4a61654b3763ad65f52283832ebf058fdf1cslive /* Recycle the completion context.
e1e8390280254f7f0580d701e583f670643d4f3fnilgun * - clear the ptrans pool
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * - put the context on the queue to be consumed by the accept thread
e1e8390280254f7f0580d701e583f670643d4f3fnilgun * context->accept_socket may be in a disconnected but reusable
06ba4a61654b3763ad65f52283832ebf058fdf1cslive * state so -don't- close it.
06ba4a61654b3763ad65f52283832ebf058fdf1cslive context->ba = apr_bucket_alloc_create(context->ptrans);
e1e8390280254f7f0580d701e583f670643d4f3fnilgunstatic winnt_conn_ctx_t *mpm_get_completion_context(int *timeout)
e1e8390280254f7f0580d701e583f670643d4f3fnilgun while (1) {
e1e8390280254f7f0580d701e583f670643d4f3fnilgun /* Grab a context off the queue */
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* We failed to grab a context off the queue, consider allocating
e1e8390280254f7f0580d701e583f670643d4f3fnilgun * a new one out of the child pool. There may be up to
2f46ce2a814d7f2b126dfb9f1b25fd64e2fbdc11rbowen * (ap_threads_per_child + num_listeners) contexts in the system
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd if (num_completion_contexts >= max_num_completion_contexts) {
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd /* All workers are busy, need to wait for one */
3b3b7fc78d1f5bfc2769903375050048ff41ff26nd static int reported = 0;
7f5b59ccc63c0c0e3e678a168f09ee6a2f51f9d0nd ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00326)
e1e8390280254f7f0580d701e583f670643d4f3fnilgun "Server ran out of threads to serve "
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung "requests. Consider raising the "
727872d18412fc021f03969b8641810d8896820bhumbedooh "ThreadsPerChild setting");
0d0ba3a410038e179b695446bb149cce6264e0abnd /* Wait for a worker to free a context. Once per second, give
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh * the caller a chance to check for shutdown. If the wait
727872d18412fc021f03969b8641810d8896820bhumbedooh * succeeds, get the context off the queue. It must be
0d0ba3a410038e179b695446bb149cce6264e0abnd * available, since there's only one consumer.
727872d18412fc021f03969b8641810d8896820bhumbedooh /* somewhat-normal condition where threads are busy */
0d0ba3a410038e179b695446bb149cce6264e0abnd ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(00327)
0d0ba3a410038e179b695446bb149cce6264e0abnd "mpm_get_completion_context: Failed to get a "
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh "free context within 1 second");
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd /* should be the unexpected, generic WAIT_FAILED */
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
0c4abc32c00611fe1d52c9661f5cc79a3f74c6d4nd "mpm_get_completion_context: "
return NULL;
sizeof(winnt_conn_ctx_t));
return NULL;
return NULL;
return context;
const char *accf_name;
int rv;
int accf;
int err_count = 0;
#if APR_HAVE_IPV6
accf = 0;
accf = 0;
#if APR_HAVE_IPV6
if (rv) {
while (!shutdown_in_progress) {
if (!context) {
int timeout;
if (!context) {
if (!timeout) {
++err_count;
char *buf;
#if APR_HAVE_IPV6
len = 0;
++err_count;
err_count = 0;
accf = 0;
++err_count;
err_count = 0;
accf = 0;
goto reinit;
err_count = 0;
err_count = 0;
sizeof(nlsd))) {
apr_bucket *b;
++err_count;
err_count = 0;
if (!accf)
if (!shutdown_in_progress) {
int rc;
#ifdef _WIN64
if (workers_may_exit) {
return NULL;
if (!rc) {
rc);
switch (CompKey) {
case IOCP_CONNECTION_ACCEPTED:
case IOCP_SHUTDOWN:
return NULL;
return NULL;
return context;
apr_bucket *e;
return AP_DECLINED;
return APR_SUCCESS;
static int requests_this_child = 0;
apr_bucket *e;
int rc;
conn_rec *c;
if (!context) {
if (ap_max_requests_per_child) {
apr_bucket_free(e);
if (e && c->aborted)
apr_bucket_free(e);
if (!c->aborted)
&disconnected);
if (!disconnected) {
int thread_to_clean)
(*thread_cnt)--;
static void create_listener_thread(void)
unsigned tid;
int num_listeners = 0;
int listener_started = 0;
int threads_created = 0;
int watch_thread;
int time_remains;
int cld;
int rv;
if (!max_requests_per_child_event) {
NULL, 0, 0);
if (!qwait_event) {
* sizeof(HANDLE));
for (i = 0; i < ap_threads_per_child; i++) {
int *score_idx;
++starting_up;
worker_main, (void *) i,
if (child_handles[i] == 0) {
goto shutdown;
*score_idx = i;
#if !APR_HAS_OTHER_CHILD
else if (cld == 0) {
while (g_blocked_threads > 0) {
for (i=g_blocked_threads; i > 0; i--) {
while (qhead) {
watch_thread = 0;
while (threads_created)
watch_thread = 0;
if (threads_created) {
for (i = 0; i < threads_created; i++) {
int *score_idx;
if (score_idx) {