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

📄 mpm_winnt.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 5 页
字号:
     * a connection.     */    workers_may_exit = 1;    /* Shutdown the worker threads */    if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {        for (i = 0; i < nthreads; i++) {            add_job(-1);        }    }    else { /* Windows NT/2000 */        /* Post worker threads blocked on the ThreadDispatch IOCompletion port */        while (g_blocked_threads > 0) {            ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,                          "Child %d: %d threads blocked on the completion port", my_pid, g_blocked_threads);            for (i=g_blocked_threads; i > 0; i--) {                PostQueuedCompletionStatus(ThreadDispatchIOCP, 0, IOCP_SHUTDOWN, NULL);            }            Sleep(1000);        }        /* Empty the accept queue of completion contexts */        while (qhead) {            CloseHandle(qhead->Overlapped.hEvent);            closesocket(qhead->accept_socket);            qhead = qhead->next;        }    }    /* Give busy worker threads a chance to service their connections */    ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,                  "Child %d: Waiting for %d threads to die.", my_pid, nthreads);    end_time = time(NULL) + 180;    while (nthreads) {        rv = wait_for_many_objects(nthreads, child_handles, end_time - time(NULL));	if (rv != WAIT_TIMEOUT) {	    rv = rv - WAIT_OBJECT_0;	    ap_assert((rv >= 0) && (rv < nthreads));	    cleanup_thread(child_handles, &nthreads, rv);            continue;        }        break;    }    /* Kill remaining threads off the hard way */    for (i = 0; i < nthreads; i++) {        TerminateThread(child_handles[i], 1);        CloseHandle(child_handles[i]);    }    ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, server_conf,                  "Child %d: All worker threads have ended.", my_pid);    CloseHandle(allowed_globals.jobsemaphore);    apr_lock_destroy(allowed_globals.jobmutex);    apr_lock_destroy(qlock);    apr_pool_destroy(pchild);    CloseHandle(exit_event);}static void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *processes){    int i;    int handle = 0;    CloseHandle(handles[position]);    CloseHandle(events[position]);    handle = (int)handles[position];    for (i = position; i < (*processes)-1; i++) {	handles[i] = handles[i + 1];	events[i] = events[i + 1];    }    (*processes)--;}static int create_process(apr_pool_t *p, HANDLE *handles, HANDLE *events, int *processes){    int rv;    char buf[1024];    char *pCommand;    char *pEnvVar;    char *pEnvBlock;    int i;    int iEnvBlockLen;    STARTUPINFO si;           /* Filled in prior to call to CreateProcess */    PROCESS_INFORMATION pi;   /* filled in on call to CreateProcess */    ap_listen_rec *lr;    DWORD BytesWritten;    HANDLE hPipeRead = NULL;    HANDLE hPipeWrite = NULL;    SECURITY_ATTRIBUTES sa = {0};      HANDLE kill_event;    LPWSAPROTOCOL_INFO  lpWSAProtocolInfo;    sa.nLength = sizeof(sa);    sa.bInheritHandle = TRUE;    sa.lpSecurityDescriptor = NULL;    /* Build the command line. Should look something like this:     * C:/apache/bin/apache.exe -f ap_server_confname      * First, get the path to the executable...     */    rv = GetModuleFileName(NULL, buf, sizeof(buf));    if (rv == sizeof(buf)) {        ap_log_error(APLOG_MARK, APLOG_CRIT, ERROR_BAD_PATHNAME, server_conf,                     "Parent: Path to Apache process too long");        return -1;    } else if (rv == 0) {        ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,                     "Parent: GetModuleFileName() returned NULL for current process.");        return -1;    }    /* Build the command line */    pCommand = apr_psprintf(p, "\"%s\"", buf);      for (i = 1; i < server_conf->process->argc; i++) {        pCommand = apr_pstrcat(p, pCommand, " \"", server_conf->process->argv[i], "\"", NULL);    }    /* Build the environment, since Win9x disrespects the active env */    pEnvVar = apr_psprintf(p, "AP_PARENT_PID=%i", parent_pid);    /*     * Win32's CreateProcess call requires that the environment     * be passed in an environment block, a null terminated block of     * null terminated strings.     */      i = 0;    iEnvBlockLen = 1;    while (_environ[i]) {        iEnvBlockLen += strlen(_environ[i]) + 1;        i++;    }    pEnvBlock = (char *)apr_pcalloc(p, iEnvBlockLen + strlen(pEnvVar) + 1);    strcpy(pEnvBlock, pEnvVar);    pEnvVar = strchr(pEnvBlock, '\0') + 1;    i = 0;    while (_environ[i]) {        strcpy(pEnvVar, _environ[i]);        pEnvVar = strchr(pEnvVar, '\0') + 1;        i++;    }    pEnvVar = '\0';    /* Create a pipe to send socket info to the child */    if (!CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0)) {        ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,                     "Parent: Unable to create pipe to child process.");        return -1;    }    /* Give the read end of the pipe (hPipeRead) to the child as stdin. The      * parent will write the socket data to the child on this pipe.     */    memset(&si, 0, sizeof(si));    memset(&pi, 0, sizeof(pi));    si.cb = sizeof(si);    si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;    si.wShowWindow = SW_HIDE;    si.hStdInput   = hPipeRead;    if (!CreateProcess(NULL, pCommand, NULL, NULL,                        TRUE,               /* Inherit handles */                       CREATE_SUSPENDED,   /* Creation flags */                       pEnvBlock,          /* Environment block */                       NULL,                       &si, &pi)) {        ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,                     "Parent: Not able to create the child process.");        /*         * We must close the handles to the new process and its main thread         * to prevent handle and memory leaks.         */         CloseHandle(pi.hProcess);        CloseHandle(pi.hThread);        return -1;    }        ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,                 "Parent: Created child process %d", pi.dwProcessId);    SetEnvironmentVariable("AP_PARENT_PID",NULL);    /* Create the exit_event, apCchild_pid */    sa.nLength = sizeof(sa);    sa.bInheritHandle = TRUE;    sa.lpSecurityDescriptor = NULL;            kill_event = CreateEvent(&sa, TRUE, FALSE, apr_psprintf(pconf,"apC%d", pi.dwProcessId));    if (!kill_event) {        ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,                     "Parent: Could not create exit event for child process");        CloseHandle(pi.hProcess);        CloseHandle(pi.hThread);        return -1;    }        /* Assume the child process lives. Update the process and event tables */    handles[*processes] = pi.hProcess;    events[*processes] = kill_event;    (*processes)++;    /* We never store the thread's handle, so close it now. */    ResumeThread(pi.hThread);    CloseHandle(pi.hThread);     /* Run the chain of open sockets. For each socket, duplicate it      * for the target process then send the WSAPROTOCOL_INFO      * (returned by dup socket) to the child.     */    for (lr = ap_listeners; lr; lr = lr->next) {        int nsd;        lpWSAProtocolInfo = apr_pcalloc(p, sizeof(WSAPROTOCOL_INFO));        apr_os_sock_get(&nsd,lr->sd);        ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, server_conf,                     "Parent: Duplicating socket %d and sending it to child process %d", nsd, pi.dwProcessId);        if (WSADuplicateSocket(nsd, pi.dwProcessId,                               lpWSAProtocolInfo) == SOCKET_ERROR) {            ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), server_conf,                         "Parent: WSADuplicateSocket failed for socket %d.", lr->sd );            return -1;        }        if (!WriteFile(hPipeWrite, lpWSAProtocolInfo, (DWORD) sizeof(WSAPROTOCOL_INFO),                       &BytesWritten,                       (LPOVERLAPPED) NULL)) {            ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,                         "Parent: Unable to write duplicated socket %d to the child.", lr->sd );            return -1;        }        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, server_conf,                     "Parent: BytesWritten = %d WSAProtocolInfo = %x20", BytesWritten, *lpWSAProtocolInfo);    }    CloseHandle(hPipeRead);    CloseHandle(hPipeWrite);            return 0;}/********************************************************************** * master_main() * This is the parent process. master_main() creates a multithreaded * child process to handle connections, then blocks waiting to receive * a shutdown, restart event or child exit event.  *  * restart_event  * - Child is signaled to die gracefully * shutdown_event  * - Child is signaled to die gracefully * child_exit_event  * - Child has died, either normally (max_request_per_child) * or abnormally (seg fault, irrecoverable error condition detected by the  * child) **********************************************************************/#define MAX_PROCESSES 50 /* must be < MAX_WAIT_OBJECTS-1 */static int master_main(server_rec *s, HANDLE shutdown_event, HANDLE restart_event){    int remaining_children_to_start = ap_daemons_to_start;    int i;    int rv, cld;    int child_num = 0;    int restart_pending = 0;    int shutdown_pending = 0;    int current_live_processes = 0; /* number of child process we know about */    HANDLE process_handles[MAX_PROCESSES];    HANDLE process_kill_events[MAX_PROCESSES];    /* Create child process      * Should only be one in this version of Apache for WIN32      */    while (remaining_children_to_start--) {        if (create_process(pconf, process_handles, process_kill_events,                            &current_live_processes) < 0) {            ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), server_conf,                         "master_main: create child process failed. Exiting.");            shutdown_pending = 1;            goto die_now;        }    }        restart_pending = shutdown_pending = 0;    if (!strcasecmp(signal_arg, "runservice"))        mpm_service_started();    /* Wait for shutdown or restart events or for child death */    process_handles[current_live_processes] = shutdown_event;    process_handles[current_live_processes+1] = restart_event;    rv = WaitForMultipleObjects(current_live_processes+2, (HANDLE *)process_handles,                                 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,                     "master_main: WaitForMultipeObjects WAIT_FAILED -- doing server shutdown");        shutdown_pending = 1;    }    else if (rv == WAIT_TIMEOUT) {        /* Hey, this cannot happen */        ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,                     "master_main: WaitForMultipeObjects with INFINITE wait exited with WAIT_TIMEOUT");        shutdown_pending = 1;    }    else if (cld == current_live_processes) {        /* shutdown_event signalled */        shutdown_pending = 1;        printf("shutdown event signaled\n");        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, s,                      "Parent: SHUTDOWN EVENT SIGNALED -- Shutting down the server.");        if (ResetEvent(shutdown_event) == 0) {            ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,                         "ResetEvent(shutdown_event)");        }    }    else if (cld == current_live_processes+1) {        /* restart_event signalled */        int children_to_kill = current_live_processes;        restart_pending = 1;        ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s,                      "Parent: RESTART EVENT SIGNALED -- Restarting the server.");        if (ResetEvent(restart_event) == 0) {            ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,                         "master_main: ResetEvent(restart_event) failed.");        }        /* Signal each child process to die          * We are making a big assumption here that the child process, once signaled,         * will REALLY go away. Since this is a restart, we do not want to hold the          * new child process up waiting for the old child to die. Remove the old          * child out of the process_handles apr_table_t and hope for the best...         */        for (i = 0; i < children_to_kill; i++) {            if (SetEvent(process_kill_events[i]) == 0)                ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), s,                             "master_main: SetEvent for child process in slot #%d failed", i);            cleanup_process(process_handles, process_kill_events, i, &current_live_processes);        }    }     else {        /* A child process must have exited because of a fatal error condition (seg fault, etc.).          * Remove the dead process          * from the process_handles and process_kill_events apr_table_t and create a new         * child process.         * TODO: Consider restarting the child immediately without looping through http_main         * and without rereading the configuration. Will need this if we ever support multiple          * children. One option, create a parent thread which waits on child death and restarts it.         * Consider, however, that if the user makes httpd.conf invalid, we want to die before         * our child tries it... otherwise we have a nasty loop.         */        restart_pending = 1;        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, server_conf,                      "Parent: CHILD PROCESS FAILED -- Restarting the child process.");        ap_assert(cld < current_live_processes);        cleanup_process(process_handles, process_kill_events, cld, &current_live_processes);        /* APD2("main_process: child in slot %d died", rv); */        /* restart_child(process_hancles, process_kill_events, cld, &current_live_processes); */    }die_now:    if (shutdown_pending)     {        int tmstart = time(NULL);                if (strcasecmp(signal_arg, "runservice")) {

⌨️ 快捷键说明

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