⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpm_winnt.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 5 页
字号:
        /* AcceptEx on the completion context. The completion context will be          * signaled when a connection is accepted.          */        if (!AcceptEx(nlsd, pCompContext->accept_socket,                      pCompContext->buff,                      0,                      PADDED_ADDR_SIZE,                       PADDED_ADDR_SIZE,                      &BytesRead,                      &pCompContext->Overlapped)) {            lasterror = apr_get_netos_error();            if (lasterror == APR_FROM_OS_ERROR(WSAEINVAL)) {                /* Hack alert. Occasionally, TransmitFile will not recycle the                  * accept socket (usually when the client disconnects early).                  * Get a new socket and try the call again.                 */                pCompContext->accept_socket = INVALID_SOCKET;                ap_log_error(APLOG_MARK, APLOG_DEBUG, lasterror, server_conf,                             "winnt_accept: AcceptEx failed. Reallocate the accept socket and try again.");                goto again;            }            else if (lasterror != APR_FROM_OS_ERROR(ERROR_IO_PENDING)) {                ap_log_error(APLOG_MARK,APLOG_ERR, lasterror, server_conf,                             "winnt_accept: AcceptEx failed. Process will exit.");                // return -1;            }            /* Wait for pending i/o */            WaitForSingleObject(pCompContext->Overlapped.hEvent, INFINITE);        }        /* When a connection is received, send an io completion notification to         * the ThreadDispatchIOCP         */        PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_CONNECTION_ACCEPTED,                                   &pCompContext->Overlapped);        if (shutdown_in_progress)            break;    }}static PCOMP_CONTEXT winnt_get_connection(PCOMP_CONTEXT pCompContext){    int requests_this_child = 0;    int rc;    DWORD BytesRead;    DWORD CompKey;    LPOVERLAPPED pol;    /* Recycle the completion context.     * - destroy the ptrans pool     * - put the context on the queue to be consumed by the accept thread     * Note: pCompContext->accept_socket may be in a disconnected     * but reusable state so -don't- close it.     */    if (pCompContext) {        apr_pool_clear(pCompContext->ptrans);        apr_pool_destroy(pCompContext->ptrans);        pCompContext->ptrans = NULL;        pCompContext->next = NULL;        apr_lock_acquire(qlock);        if (qtail)            qtail->next = pCompContext;        else            qhead = pCompContext;        qtail = pCompContext;        apr_lock_release(qlock);    }    g_blocked_threads++;            while (1) {        if (workers_may_exit) {            g_blocked_threads--;            return NULL;        }        rc = GetQueuedCompletionStatus(ThreadDispatchIOCP, &BytesRead, &CompKey,                                       &pol, INFINITE);        if (!rc) {            rc = apr_get_os_error();            ap_log_error(APLOG_MARK,APLOG_DEBUG, rc, server_conf,                             "Child %d: GetQueuedComplationStatus returned %d", my_pid, rc);            continue;        }        switch (CompKey) {        case IOCP_CONNECTION_ACCEPTED:            pCompContext = CONTAINING_RECORD(pol, COMP_CONTEXT, Overlapped);            break;        case IOCP_SHUTDOWN:            g_blocked_threads--;            return NULL;        default:            g_blocked_threads--;            return NULL;        }        break;    }    g_blocked_threads--;        if ((rc = apr_pool_create(&pCompContext->ptrans, NULL)) != APR_SUCCESS) {        ap_log_error(APLOG_MARK,APLOG_DEBUG, rc, server_conf,                     "Child %d: apr_pool_create failed with rc %d", my_pid, rc);    }    /* Get the local & remote address */    GetAcceptExSockaddrs(pCompContext->buff,                         0,                         PADDED_ADDR_SIZE,                         PADDED_ADDR_SIZE,                         &pCompContext->sa_server,                         &pCompContext->sa_server_len,                         &pCompContext->sa_client,                         &pCompContext->sa_client_len);    return pCompContext;}/* * worker_main() * Main entry point for the worker threads. Worker threads block in  * win*_get_connection() awaiting a connection to service. */static void worker_main(int thread_num){    PCOMP_CONTEXT context = NULL;    apr_os_sock_info_t sockinfo;    while (1) {        conn_rec *c;        apr_int32_t disconnected;        ap_update_child_status(0, thread_num, SERVER_READY,                                (request_rec *) NULL);        /* Grab a connection off the network */        if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {            context = win9x_get_connection(context);        }        else {            context = winnt_get_connection(context);        }        if (!context)            break;        sockinfo.os_sock = &context->accept_socket;        sockinfo.local   = context->sa_server;        sockinfo.remote  = context->sa_client;        sockinfo.family  = APR_INET;        sockinfo.type    = SOCK_STREAM;        apr_os_sock_make(&context->sock, &sockinfo, context->ptrans);        c = ap_new_connection(context->ptrans, server_conf, context->sock,                              thread_num);        if (c) {            ap_process_connection(c);            apr_getsocketopt(context->sock, APR_SO_DISCONNECTED, &disconnected);            if (!disconnected) {                context->accept_socket = INVALID_SOCKET;                ap_lingering_close(c);            }        }        else {            /* ap_new_connection closes the socket on failure */            context->accept_socket = INVALID_SOCKET;        }    }    ap_update_child_status(0, thread_num, SERVER_DEAD, (request_rec *) NULL);    ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,                 "Child %d: Thread exiting.", my_pid);}static void cleanup_thread(thread *handles, int *thread_cnt, int thread_to_clean){    int i;    CloseHandle(handles[thread_to_clean]);    for (i = thread_to_clean; i < ((*thread_cnt) - 1); i++)	handles[i] = handles[i + 1];    (*thread_cnt)--;}/* * child_main()  * Entry point for the main control thread for the child process.  * This thread creates the accept thread, worker threads and * monitors the child process for maintenance and shutdown * events. */static void child_main(){    apr_status_t status;    HANDLE child_events[2];    char* exit_event_name;    int nthreads = ap_threads_per_child;    int tid;    thread *child_handles;    int rv;    time_t end_time;    int i;    int cld;    /* This is the child process or we are running in single process mode. */    exit_event_name = apr_psprintf(pconf, "apC%d", my_pid);    setup_signal_names(apr_psprintf(pconf,"ap%d", parent_pid));    if (one_process) {        /* Single process mode */        apr_lock_create(&start_mutex, APR_MUTEX, APR_CROSS_PROCESS,                        signal_name_prefix, pconf);        exit_event = CreateEvent(NULL, TRUE, FALSE, exit_event_name);    }    else {        /* Child process mode */        apr_lock_child_init(&start_mutex, signal_name_prefix, pconf);        exit_event = OpenEvent(EVENT_ALL_ACCESS, FALSE, exit_event_name);        ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,                     "Child %d: exit_event_name = %s", my_pid, exit_event_name);    }    /* Initialize the child_events */    maintenance_event = CreateEvent(NULL, TRUE, FALSE, NULL);    child_events[0] = exit_event;    child_events[1] = maintenance_event;    ap_assert(start_mutex);    ap_assert(exit_event);    ap_assert(maintenance_event);    apr_pool_create(&pchild, pconf);    allowed_globals.jobsemaphore = CreateSemaphore(NULL, 0, 1000000, NULL);    apr_lock_create(&allowed_globals.jobmutex, APR_MUTEX, APR_INTRAPROCESS, NULL, pchild);    /*     * Wait until we have permission to start accepting connections.     * start_mutex is used to ensure that only one child ever     * goes into the listen/accept loop at once.     */    status = apr_lock_acquire(start_mutex);    if (status != APR_SUCCESS) {	ap_log_error(APLOG_MARK,APLOG_ERR, status, server_conf,                     "Child %d: Failed to acquire the start_mutex. Process will exit.", my_pid);        signal_parent(0);	/* tell parent to die */	exit(0);    }    ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,                  "Child %d: Acquired the start mutex.", my_pid);    /*     * Create the worker thread dispatch IOCompletionPort     * on Windows NT/2000     */    if (osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) {        /* Create the worker thread dispatch IOCP */        ThreadDispatchIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE,                                                    NULL,                                                    0,                                                    0); /* CONCURRENT ACTIVE THREADS */        apr_lock_create(&qlock, APR_MUTEX, APR_INTRAPROCESS, NULL, pchild);    }    /*      * Create the pool of worker threads     */    ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,                  "Child %d: Starting %d worker threads.", my_pid, nthreads);    child_handles = (thread) alloca(nthreads * sizeof(int));    for (i = 0; i < nthreads; i++) {        ap_update_child_status(0, i, SERVER_STARTING, (request_rec *) NULL);        child_handles[i] = (thread) _beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE) worker_main,                                                   (void *) i, 0, &tid);    }    /*      * Start the accept thread     */    if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {        _beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE) win9x_accept,                       (void *) i, 0, &tid);    } else {        /* Start an accept thread per listener */        SOCKET nlsd; /* native listening sock descriptor */        ap_listen_rec *lr;        for (lr = ap_listeners; lr; lr = lr->next) {            if (lr->sd != NULL) {                apr_os_sock_get(&nlsd, lr->sd);                _beginthreadex(NULL, 1000, (LPTHREAD_START_ROUTINE) winnt_accept,                               (void *) nlsd, 0, &tid);            }        }    }    /* Wait for one of three events:     * exit_event:      *    The exit_event is signaled by the parent process to notify      *    the child that it is time to exit.     *     * maintenance_event:      *    This event is signaled by the worker thread pool to direct      *    this thread to create more completion contexts.     *     * TIMEOUT:     *    To do periodic maintenance on the server (check for thread exits,     *    number of completion contexts, etc.)     */    while (1) {        rv = WaitForMultipleObjects(2, (HANDLE *) child_events, FALSE, INFINITE);        cld = rv - WAIT_OBJECT_0;        if (rv == WAIT_FAILED) {            /* Something serious is wrong */            ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,                         "Child %d: WAIT_FAILED -- shutting down server");            break;        }        else if (rv == WAIT_TIMEOUT) {            /* Hey, this cannot happen */            ap_log_error(APLOG_MARK, APLOG_CRIT, APR_SUCCESS, server_conf,                         "Child %d: WAIT_TIMEOUT -- shutting down server", my_pid);            break;        }        else if (cld == 0) {            /* Exit event was signaled */            ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,                         "Child %d: Exit event signaled. Child process is ending.", my_pid);            break;        }        else {            /* Child maintenance event signaled */            ResetEvent(maintenance_event);            ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,                         "Child %d: Child maintenance event signaled.", my_pid);        }    }    /* Setting is_graceful will cause keep-alive connections to be closed     * rather then block on the next network read.     */    is_graceful = 1;    /* Setting shutdown_in_progress prevents new connections from     * being accepted but allows the worker threads to continue     * handling connections that have already been accepted.     */    shutdown_in_progress = 1;    /* Close the listening sockets */    {        ap_listen_rec *lr;        for (lr = ap_listeners; lr ; lr = lr->next) {            apr_socket_close(lr->sd);        }    }    /* Give the worker threads time to handle already accepted connections */    Sleep(1000);    /* Release the start_mutex to let the new process (in the restart     * scenario) a chance to begin accepting and servicing requests      */    ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,                  "Child %d: Releasing the start mutex", my_pid);    apr_lock_release(start_mutex);    /* Tell the worker threads they may exit when done handling

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -