stoddard 99/08/11 09:03:56
Modified: mpm/src/modules/mpm/winnt winnt.c Log: Still a complete hacked up mess, but getting better! Revision Changes Path 1.3 +201 -139 apache-2.0/mpm/src/modules/mpm/winnt/winnt.c Index: winnt.c =================================================================== RCS file: /home/cvs/apache-2.0/mpm/src/modules/mpm/winnt/winnt.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- winnt.c 1999/08/05 22:05:47 1.2 +++ winnt.c 1999/08/11 16:03:55 1.3 @@ -187,8 +187,26 @@ ap_start_restart(1); } -static ap_listen_rec *old_listeners; +/* + * Find a listener which is ready for accept(). This advances the + * head_listener global. + */ static ap_listen_rec *head_listener; +static ap_inline ap_listen_rec *find_ready_listener(fd_set * main_fds) +//static ap_listen_rec *find_ready_listener(fd_set * main_fds) +{ + ap_listen_rec *lr; + + lr = head_listener; + do { + if (FD_ISSET(lr->fd, main_fds)) { + head_listener = lr->next; + return (lr); + } + lr = lr->next; + } while (lr != head_listener); + return NULL; +} static int setup_listeners(pool *pconf, server_rec *s) { ap_listen_rec *lr; @@ -200,56 +218,80 @@ for (lr = ap_listeners; lr; lr = lr->next) { num_listeners++; } + + /* Should we turn the list into a ring ?*/ + head_listener = ap_listeners; + return num_listeners; } -static int find_listener(ap_listen_rec *lr) +static int setup_inherited_listeners(pool *p, server_rec *s) { - ap_listen_rec *or; + WSAPROTOCOL_INFO WSAProtocolInfo; + HANDLE pipe; + ap_listen_rec *lr; + DWORD BytesRead; + int num_listeners = 0; + int fd; - for (or = old_listeners; or; or = or->next) { - if (!memcmp(&or->local_addr, &lr->local_addr, sizeof(or->local_addr))) { -// or->used = 1; - return or->fd; - } + /* Setup the listeners */ + listenmaxfd = -1; + FD_ZERO(&listenfds); + + /* Set up a default listener if necessary */ + if (ap_listeners == NULL) { + struct sockaddr_in local_addr; + ap_listen_rec *new; + local_addr.sin_family = AF_INET; + local_addr.sin_addr.s_addr = htonl(INADDR_ANY); + local_addr.sin_port = htons(s->port ? s->port : DEFAULT_HTTP_PORT); + new = malloc(sizeof(ap_listen_rec)); + new->local_addr = local_addr; + new->fd = -1; + new->next = ap_listeners; + ap_listeners = new; } - return -1; -} + /* Open the pipe to the parent process to receive the inherited socket + * data. The sockets have been set to listening in the parent process. + */ + pipe = GetStdHandle(STD_INPUT_HANDLE); + for (lr = ap_listeners; lr; lr = lr->next) { + if (!ReadFile(pipe, &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO), + &BytesRead, (LPOVERLAPPED) NULL)) { + ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_CRIT, server_conf, + "setup_inherited_listeners: Unable to read socket data from parent"); + exit(1); + } + fd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, + &WSAProtocolInfo, 0, 0); + if (fd == INVALID_SOCKET) { + ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_CRIT, server_conf, + "setup_inherited_listeners: WSASocket failed to get inherit the socket."); + exit(1); + } + if (fd >= 0) { + FD_SET(fd, &listenfds); + if (fd > listenmaxfd) + listenmaxfd = fd; + } + ap_note_cleanups_for_socket(p, fd); + } + CloseHandle(pipe); -static void close_unused_listeners(void) -{ - ap_listen_rec *or, *next; - for (or = old_listeners; or; or = next) { - next = or->next; -// if (!or->used) - closesocket(or->fd); - free(or); + for (lr = ap_listeners; lr; lr = lr->next) { + num_listeners++; } - old_listeners = NULL; -} -/* - * Find a listener which is ready for accept(). This advances the - * head_listener global. - */ -static ap_inline ap_listen_rec *find_ready_listener(fd_set * main_fds) -//static ap_listen_rec *find_ready_listener(fd_set * main_fds) -{ - ap_listen_rec *lr; + /* turn the list into a ring ?*/ +// lr->next = ap_listeners; + head_listener = ap_listeners; - lr = head_listener; - do { - if (FD_ISSET(lr->fd, main_fds)) { - head_listener = lr->next; - return (lr); - } - lr = lr->next; - } while (lr != head_listener); - return NULL; + return num_listeners; } + /* * Signalling Apache on NT. * @@ -349,6 +391,12 @@ } } +API_EXPORT(int) ap_graceful_stop_signalled(void) +{ + /* XXX - Does this really work? - Manoj */ + return is_graceful; +} + /********************************************************************** * Multithreaded implementation @@ -421,6 +469,27 @@ * connection already in progress (in child_sub_main()). We'd have to * get that to poll on the exit event. */ +int service_init() +{ +} + +/* +int service_init() +{ + common_init(); + + ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root)); + if (ap_registry_get_service_conf(pconf, ap_server_confname, sizeof(ap_server_confname), + ap_server_argv0)) + return FALSE; + + ap_setup_prelinked_modules(); + server_conf = ap_read_config(pconf, ptrans, ap_server_confname); + ap_log_pid(pconf, ap_pid_fname); + post_parse_init(); + return TRUE; +} +*/ /* * Definition of jobs, shared by main and worker threads. @@ -584,7 +653,7 @@ while (1) { BUFF *conn_io; - request_rec *r; +// request_rec *r; /* * (Re)initialize this child to a pre-connection state. @@ -657,8 +726,8 @@ current_conn = ap_new_connection(ptrans, server_conf, conn_io, (struct sockaddr_in *) &sa_client, - (struct sockaddr_in *) &sa_server, - child_num, 0); /* Set my_thread_num to 0 for now */ + (struct sockaddr_in *) &sa_server);//, + //child_num, 0); /* Set my_thread_num to 0 for now */ ap_process_connection(current_conn); } @@ -750,71 +819,7 @@ "%s_restart", signal_name_prefix); } -static void setup_inherited_listeners(pool *p) -{ - HANDLE pipe; - ap_listen_rec *lr; - int fd; - WSAPROTOCOL_INFO WSAProtocolInfo; - DWORD BytesRead; - - /* Open the pipe to the parent process to receive the inherited socket - * data. The sockets have been set to listening in the parent process. - */ - pipe = GetStdHandle(STD_INPUT_HANDLE); - - /* Setup the listeners */ - listenmaxfd = -1; - FD_ZERO(&listenfds); - lr = ap_listeners; - - FD_ZERO(&listenfds); - for (;;) { - fd = find_listener(lr); - if (fd < 0) { - if (!ReadFile(pipe, - &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO), - &BytesRead, - (LPOVERLAPPED) NULL)){ - ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_CRIT, server_conf, - "setup_inherited_listeners: Unable to read socket data from parent"); - exit(1); - } - fd = WSASocket(FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - &WSAProtocolInfo, - 0, - 0); - if (fd == INVALID_SOCKET) { - ap_log_error(APLOG_MARK, APLOG_WIN32ERROR|APLOG_CRIT, server_conf, - "setup_inherited_listeners: WSASocket failed to get inherit the socket."); - exit(1); - } -// APD2("setup_inherited_listeners: WSASocket() returned socket %d", fd); - } - else { - ap_note_cleanups_for_socket(p, fd); - } - if (fd >= 0) { - FD_SET(fd, &listenfds); - if (fd > listenmaxfd) - listenmaxfd = fd; - } - lr->fd = fd; - if (lr->next == NULL) - break; - lr = lr->next; - } - /* turn the list into a ring */ - lr->next = ap_listeners; - head_listener = ap_listeners; - close_unused_listeners(); - CloseHandle(pipe); - return; -} - /* * worker_main() is main loop for the child process. The loop in * this function becomes the controlling thread for the actually working @@ -853,7 +858,7 @@ my_pid = getpid(); - ap_restart_time = time(NULL); +// ap_restart_time = time(NULL); // reinit_scoreboard(pconf); @@ -886,7 +891,7 @@ setup_listeners(pconf, server_conf); } else { /* Get listeners from the parent process */ - setup_inherited_listeners(pconf); + setup_inherited_listeners(pconf, server_conf); } if (listenmaxfd == -1) { @@ -1095,20 +1100,17 @@ // APD4("cleanup_processes: removed child in slot %d handle %d, max=%d", position, handle, *processes); } -static int create_process(pool *p, HANDLE *handles, HANDLE *events, - int *processes, int *child_num, char *kill_event_name) +static int create_process(pool *p, HANDLE *handles, HANDLE *events, int *processes) { - int rv, i; - HANDLE kill_event; + int rv; char buf[1024]; - char exit_event_name[40]; /* apPID_C# */ char *pCommand; char *pEnvBlock; STARTUPINFO si; /* Filled in prior to call to CreateProcess */ PROCESS_INFORMATION pi; /* filled in on call to CreateProces */ - LPWSAPROTOCOL_INFO lpWSAProtocolInfo; + ap_listen_rec *lr; DWORD BytesWritten; HANDLE hPipeRead = NULL; @@ -1134,17 +1136,6 @@ return -1; } - /* Create the exit event (apPID_C#). Parent signals this event to tell the - * child to exit - */ - ap_snprintf(exit_event_name, sizeof(exit_event_name), "%s_C%d", kill_event_name, ++(*child_num)); - kill_event = CreateEvent(NULL, TRUE, FALSE, exit_event_name); - if (!kill_event) { - ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf, - "Parent: Could not create exit event for child process"); - return -1; - } - // pCommand = ap_psprintf(p, "\"%s\" -f \"%s\"", buf, ap_server_confname); pCommand = ap_psprintf(p, "\"%s\" -f \"%s\"", buf, SERVER_CONFIG_FILE); @@ -1155,7 +1146,7 @@ return -1; } - pEnvBlock = ap_psprintf(p, "AP_PARENT_PID=%d\0AP_CHILD_NUM=%d\0\0",parent_pid,*child_num); + pEnvBlock = ap_psprintf(p, "AP_PARENT_PID=%d\0\0",parent_pid); /* Give the read in of the pipe (hPipeRead) to the child as stdin. The * parent will write the socket data to the child on this pipe. @@ -1168,9 +1159,9 @@ si.hStdInput = hPipeRead; if (!CreateProcess(NULL, pCommand, NULL, NULL, - TRUE, /* Inherit handles */ - 0, /* Creation flags */ - pEnvBlock, /* Environment block */ + TRUE, /* Inherit handles */ + CREATE_SUSPENDED, /* Creation flags */ + pEnvBlock, /* Environment block */ NULL, &si, &pi)) { ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf, @@ -1185,15 +1176,30 @@ return -1; } else { + HANDLE kill_event; + LPWSAPROTOCOL_INFO lpWSAProtocolInfo; + ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, server_conf, "Parent: Created child process %d", pi.dwProcessId); + /* Create the exit_event, apCHILD_PID */ + kill_event = CreateEvent(NULL, TRUE, FALSE, + ap_psprintf(pconf,"ap%d", pi.dwProcessId)); + if (!kill_event) { + ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, 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 @@ -1290,7 +1296,7 @@ */ while (remaining_children_to_start--) { if (create_process(pconf, process_handles, process_kill_events, - ¤t_live_processes, &child_num, signal_prefix_string) < 0) { + ¤t_live_processes) < 0) { ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "master_main: create child process failed. Exiting."); shutdown_pending = 1; @@ -1388,8 +1394,6 @@ ap_assert(rv != WAIT_FAILED); cld = rv - WAIT_OBJECT_0; ap_assert(rv < current_live_processes); -// APD4("main_process: child in #%d handle %d died, left=%d", -// rv, process_handles[rv], current_live_processes); cleanup_process(process_handles, process_kill_events, cld, ¤t_live_processes); } for (i = 0; i < current_live_processes; i++) { @@ -1445,11 +1449,9 @@ API_EXPORT(int) ap_mpm_run(pool *_pconf, pool *plog, server_rec *s ) { - int child_num; char* exit_event_name; - int i; - time_t tmstart; +// time_t tmstart; HANDLE shutdown_event; /* used to signal shutdown to parent */ HANDLE restart_event; /* used to signal a restart to parent */ @@ -1458,16 +1460,14 @@ if ((parent_pid != my_pid) || one_process) { /* Child process */ - child_num = atoi(getenv("AP_CHILD_NUM")); - exit_event_name = ap_psprintf(pconf, "ap_%d_C%d", parent_pid, child_num); + exit_event_name = ap_psprintf(pconf, "ap%d", my_pid); exit_event = open_event(exit_event_name); - setup_signal_names(ap_psprintf(pconf,"ap_%d", parent_pid)); + setup_signal_names(ap_psprintf(pconf,"ap%d", parent_pid)); start_mutex = ap_open_mutex(signal_name_prefix); ap_assert(start_mutex); worker_main(); - destroy_event(exit_event); } else { @@ -1480,7 +1480,7 @@ if (!restart) { /* service_set_status(SERVICE_START_PENDING);*/ - setup_signal_names(ap_psprintf(pconf,"ap_%d", parent_pid)); + setup_signal_names(ap_psprintf(pconf,"ap%d", parent_pid)); /* Create shutdown event, apPID_shutdown, where PID is the parent * Apache process ID. Shutdown is signaled by 'apache -k shutdown'. @@ -1510,7 +1510,8 @@ * Ths start mutex is used during a restart to prevent more than one * child process from entering the accept loop at once. */ - start_mutex = ap_create_mutex(signal_prefix_string); + start_mutex = ap_create_mutex(signal_name_prefix); +// start_mutex = ap_create_mutex(ap_psprintf(pconf,"ap%d", parent_pid)); /* TOTD: Add some code to detect failure */ } @@ -1632,6 +1633,67 @@ } ap_cpystrn(ap_coredump_dir, fname, sizeof(ap_coredump_dir)); return NULL; +} +/* +static int +map_rv(int rv) +{ + switch(rv) + { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + return(MULTI_OK); + case WAIT_TIMEOUT: + return(MULTI_TIMEOUT); + case WAIT_FAILED: + return(MULTI_ERR); + default: + assert(0); + } + + assert(0); + return(0); +} +*/ + +/* +API_EXPORT(mutex *) ap_open_mutex(char *name) +{ + return(OpenMutex(MUTEX_ALL_ACCESS, FALSE, name)); +} +*/ + +struct ap_thread_mutex { + HANDLE _mutex; +}; + + +API_EXPORT(ap_thread_mutex *) ap_thread_mutex_new(void) +{ + ap_thread_mutex *mtx; + + mtx = malloc(sizeof(ap_thread_mutex)); + mtx->_mutex = CreateMutex(NULL, FALSE, NULL); + return mtx; +} + + +API_EXPORT(void) ap_thread_mutex_lock(ap_thread_mutex *mtx) +{ + int rv; + rv = WaitForSingleObject(mtx->_mutex, INFINITE); +} + + +API_EXPORT(void) ap_thread_mutex_unlock(ap_thread_mutex *mtx) +{ + ReleaseMutex(mtx->_mutex); +} + +API_EXPORT(void) ap_thread_mutex_destroy(ap_thread_mutex *mtx) +{ + CloseHandle(mtx->_mutex); + free(mtx); } static const command_rec winnt_cmds[] = {