📄 mpm_winnt.c
字号:
/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * Portions of this software are based upon public domain software * originally written at the National Center for Supercomputing Applications, * University of Illinois, Urbana-Champaign. */#define CORE_PRIVATE #include "httpd.h" #include "http_main.h" #include "http_log.h" #include "http_config.h" /* for read_config */ #include "http_core.h" /* for get_remote_host */ #include "http_connection.h"#include "apr_portable.h"#include "apr_getopt.h"#include "apr_strings.h"#include "apr_lib.h"#include "ap_mpm.h"#include "ap_config.h"#include "ap_listen.h"#include "mpm_default.h"#include "mpm_winnt.h"#include "mpm_common.h"#include "scoreboard.h"typedef HANDLE thread;#ifdef CONTAINING_RECORD#undef CONTAINING_RECORD#endif#define CONTAINING_RECORD(address, type, field) ((type *)( \ (PCHAR)(address) - \ (PCHAR)(&((type *)0)->field)))#define PADDED_ADDR_SIZE sizeof(SOCKADDR_IN)+16typedef struct CompContext { struct CompContext *next; OVERLAPPED Overlapped; apr_socket_t *sock; SOCKET accept_socket; char buff[2*PADDED_ADDR_SIZE]; struct sockaddr *sa_server; int sa_server_len; struct sockaddr *sa_client; int sa_client_len; apr_pool_t *ptrans;} COMP_CONTEXT, *PCOMP_CONTEXT;typedef enum { IOCP_CONNECTION_ACCEPTED = 1, IOCP_WAIT_FOR_RECEIVE = 2, IOCP_WAIT_FOR_TRANSMITFILE = 3, IOCP_SHUTDOWN = 4} io_state_e;/* Queue for managing the passing of COMP_CONTEXTs from * the accept thread to the worker threads and back again */apr_lock_t *qlock;COMP_CONTEXT *qhead = NULL;COMP_CONTEXT *qtail = NULL;static HANDLE ThreadDispatchIOCP = NULL;/* Definitions of WINNT MPM specific config globals */static server_rec *server_conf;static apr_pool_t *pconf;static apr_pool_t *pchild = NULL;static int workers_may_exit = 0;static int shutdown_in_progress = 0;static unsigned int g_blocked_threads = 0;static int ap_max_requests_per_child=0;static char *ap_pid_fname = NULL;static HANDLE shutdown_event; /* used to signal the parent to shutdown */static HANDLE restart_event; /* used to signal the parent to restart */static HANDLE exit_event; /* used by parent to signal the child to exit */static HANDLE maintenance_event;static char ap_coredump_dir[MAX_STRING_LEN];static int one_process = 0;static char const* signal_arg;OSVERSIONINFO osver; /* VER_PLATFORM_WIN32_NT */apr_lock_t *start_mutex;static DWORD my_pid;static DWORD parent_pid;int ap_threads_per_child = 0;int ap_daemons_to_start=0;/* ap_get_max_daemons and ap_my_generation are used by the scoreboard * code */ap_generation_t volatile ap_my_generation=0; /* Used by the scoreboard *//* This is the helper code to resolve late bound entry points * missing from one or more releases of the Win32 API... * but it sure would be nice if we didn't duplicate this code * from the APR ;-) */static const char* const lateDllName[DLL_defined] = { "kernel32", "advapi32", "mswsock", "ws2_32" };static HMODULE lateDllHandle[DLL_defined] = { NULL, NULL, NULL, NULL };FARPROC ap_load_dll_func(ap_dlltoken_e fnLib, char* fnName, int ordinal){ if (!lateDllHandle[fnLib]) { lateDllHandle[fnLib] = LoadLibrary(lateDllName[fnLib]); if (!lateDllHandle[fnLib]) return NULL; } if (ordinal) return GetProcAddress(lateDllHandle[fnLib], (char *) ordinal); else return GetProcAddress(lateDllHandle[fnLib], fnName);}/* To share the semaphores with other processes, we need a NULL ACL * Code from MS KB Q106387 */static PSECURITY_ATTRIBUTES GetNullACL(){ PSECURITY_DESCRIPTOR pSD; PSECURITY_ATTRIBUTES sa; sa = (PSECURITY_ATTRIBUTES) LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES)); pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSD == NULL || sa == NULL) { return NULL; } apr_set_os_error(0); if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) || apr_get_os_error()) { LocalFree( pSD ); LocalFree( sa ); return NULL; } if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL) NULL, FALSE) || apr_get_os_error()) { LocalFree( pSD ); LocalFree( sa ); return NULL; } sa->nLength = sizeof(sa); sa->lpSecurityDescriptor = pSD; sa->bInheritHandle = TRUE; return sa;}static void CleanNullACL( void *sa ) { if( sa ) { LocalFree( ((PSECURITY_ATTRIBUTES)sa)->lpSecurityDescriptor); LocalFree( sa ); }}/* * The Win32 call WaitForMultipleObjects will only allow you to wait for * a maximum of MAXIMUM_WAIT_OBJECTS (current 64). Since the threading * model in the multithreaded version of apache wants to use this call, * we are restricted to a maximum of 64 threads. This is a simplistic * routine that will increase this size. */static DWORD wait_for_many_objects(DWORD nCount, CONST HANDLE *lpHandles, DWORD dwSeconds){ time_t tStopTime; DWORD dwRet = WAIT_TIMEOUT; DWORD dwIndex=0; BOOL bFirst = TRUE; tStopTime = time(NULL) + dwSeconds; do { if (!bFirst) Sleep(1000); else bFirst = FALSE; for (dwIndex = 0; dwIndex * MAXIMUM_WAIT_OBJECTS < nCount; dwIndex++) { dwRet = WaitForMultipleObjects( min(MAXIMUM_WAIT_OBJECTS, nCount - (dwIndex * MAXIMUM_WAIT_OBJECTS)), lpHandles + (dwIndex * MAXIMUM_WAIT_OBJECTS), 0, 0); if (dwRet != WAIT_TIMEOUT) { break; } } } while((time(NULL) < tStopTime) && (dwRet == WAIT_TIMEOUT)); return dwRet;}/* * Signalling Apache on NT. * * Under Unix, Apache can be told to shutdown or restart by sending various * signals (HUP, USR, TERM). On NT we don't have easy access to signals, so * we use "events" instead. The parent apache process goes into a loop * where it waits forever for a set of events. Two of those events are * called * * apPID_shutdown * apPID_restart * * (where PID is the PID of the apache parent process). When one of these * is signalled, the Apache parent performs the appropriate action. The events * can become signalled through internal Apache methods (e.g. if the child * finds a fatal error and needs to kill its parent), via the service * control manager (the control thread will signal the shutdown event when * requested to stop the Apache service), from the -k Apache command line, * or from any external program which finds the Apache PID from the * httpd.pid file. * * The signal_parent() function, below, is used to signal one of these events. * It can be called by any child or parent process, since it does not * rely on global variables. * * On entry, type gives the event to signal. 0 means shutdown, 1 means * graceful restart. *//* * Initialise the signal names, in the global variables signal_name_prefix, * signal_restart_name and signal_shutdown_name. */#define MAX_SIGNAL_NAME 30 /* Long enough for apPID_shutdown, where PID is an int */char signal_name_prefix[MAX_SIGNAL_NAME];char signal_restart_name[MAX_SIGNAL_NAME]; char signal_shutdown_name[MAX_SIGNAL_NAME];void setup_signal_names(char *prefix){ apr_snprintf(signal_name_prefix, sizeof(signal_name_prefix), prefix); apr_snprintf(signal_shutdown_name, sizeof(signal_shutdown_name), "%s_shutdown", signal_name_prefix); apr_snprintf(signal_restart_name, sizeof(signal_restart_name), "%s_restart", signal_name_prefix); }void signal_parent(int type){ HANDLE e; char *signal_name; /* after updating the shutdown_pending or restart flags, we need * to wake up the parent process so it can see the changes. The * parent will normally be waiting for either a child process * to die, or for a signal on the "spache-signal" event. So set the * "apache-signal" event here. */ if (one_process) { return; } switch(type) { case 0: signal_name = signal_shutdown_name; break; case 1: signal_name = signal_restart_name; break; default: return; } e = OpenEvent(EVENT_ALL_ACCESS, FALSE, signal_name); if (!e) { /* Um, problem, can't signal the parent, which means we can't * signal ourselves to die. Ignore for now... */ ap_log_error(APLOG_MARK, APLOG_EMERG, apr_get_os_error(), server_conf, "OpenEvent on %s event", signal_name); return; } if (SetEvent(e) == 0) { /* Same problem as above */ ap_log_error(APLOG_MARK, APLOG_EMERG, apr_get_os_error(), server_conf, "SetEvent on %s event", signal_name); CloseHandle(e); return; } CloseHandle(e);}static int volatile is_graceful = 0;AP_DECLARE(int) ap_graceful_stop_signalled(void){ return is_graceful;}AP_DECLARE(void) ap_start_shutdown(void){ signal_parent(0);}AP_DECLARE(void) ap_start_restart(int gracefully){ is_graceful = gracefully; signal_parent(1);}/* * find_ready_listener() * Only used by Win9* and should go away when the win9*_accept() function is * reimplemented using apr_poll(). */static ap_listen_rec *head_listener;static APR_INLINE ap_listen_rec *find_ready_listener(fd_set * main_fds){ ap_listen_rec *lr; SOCKET nsd; for (lr = head_listener; lr ; lr = lr->next) { apr_os_sock_get(&nsd, lr->sd); if (FD_ISSET(nsd, main_fds)) { head_listener = lr->next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -