summaryrefslogtreecommitdiffstats
path: root/server/mpm/winnt/mpm_winnt.c
diff options
context:
space:
mode:
authorBill Stoddard <stoddard@apache.org>1999-08-17 21:51:43 +0200
committerBill Stoddard <stoddard@apache.org>1999-08-17 21:51:43 +0200
commite58d38b8ca5622d8166b01e13b866eda4c3196cd (patch)
tree14aef20b1e63a6bc3393d9fe702df855faf65d76 /server/mpm/winnt/mpm_winnt.c
parentServer will build and serve static pages (page size < bufsize) with the appro... (diff)
downloadapache2-e58d38b8ca5622d8166b01e13b866eda4c3196cd.tar.xz
apache2-e58d38b8ca5622d8166b01e13b866eda4c3196cd.zip
More cleanup...
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@83708 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--server/mpm/winnt/mpm_winnt.c544
1 files changed, 189 insertions, 355 deletions
diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c
index 1c4b384f76..8c9c25897c 100644
--- a/server/mpm/winnt/mpm_winnt.c
+++ b/server/mpm/winnt/mpm_winnt.c
@@ -70,8 +70,9 @@
#include "../os/win32/getopt.h"
#include "mpm_default.h"
#include "../os/win32/iol_socket.h"
+
/*
- * Actual definitions of WINNT MPM specific config globals
+ * Definitions of WINNT MPM specific config globals
*/
int ap_max_requests_per_child=0;
int ap_daemons_to_start=0;
@@ -80,114 +81,23 @@ static int ap_threads_per_child = 0;
static int workers_may_exit = 0;
static int max_requests_per_child = 0;
static int requests_this_child;
-static int num_listenfds = 0;
+
static struct pollfd *listenfds;
+static int num_listenfds = 0;
+int listenmaxfd = -1;
+
static pool *pconf; /* Pool for config stuff */
static char ap_coredump_dir[MAX_STRING_LEN];
static server_rec *server_conf;
-/*static int sd; ZZZ why is the global...? Only seems to be needed on Win32*/
-
-/* one_process --- debugging mode variable; can be set from the command line
- * with the -X flag. If set, this gets you the child_main loop running
- * in the process which originally started up (no detach, no make_child),
- * which is a pretty nice debugging environment. (You'll get a SIGHUP
- * early in standalone_main; just continue through. This is the server
- * trying to kill off any child processes which it might have lying
- * around --- Apache doesn't keep track of their pids, it just sends
- * SIGHUP to the process group, ignoring it in the root process.
- * Continue through and you'll be fine.).
- */
static int one_process = 0;
-
-#ifdef DEBUG_SIGSTOP
-int raise_sigstop_flags;
-#endif
-
-
-/* *Non*-shared winnt.c globals... */
event *exit_event;
mutex *start_mutex;
int my_pid;
int parent_pid;
-int listenmaxfd = -1;
-
-/* a clean exit from a child with proper cleanup
- static void clean_child_exit(int code) __attribute__ ((noreturn));
-void clean_child_exit(int code)
-{
- if (pchild) {
- ap_destroy_pool(pchild);
- }
- exit(code);
-}
-*/
-/*****************************************************************
- * Connection structures and accounting...
- */
-
-/* volatile just in case */
-static int volatile shutdown_pending;
-static int volatile restart_pending;
-static int volatile is_graceful;
-
-/*
- * ap_start_shutdown() and ap_start_restart(), below, are a first stab at
- * functions to initiate shutdown or restart without relying on signals.
- * Previously this was initiated in sig_term() and restart() signal handlers,
- * but we want to be able to start a shutdown/restart from other sources --
- * e.g. on Win32, from the service manager. Now the service manager can
- * call ap_start_shutdown() or ap_start_restart() as appropiate. Note that
- * these functions can also be called by the child processes, since global
- * variables are no longer used to pass on the required action to the parent.
- *
- * These should only be called from the parent process itself, since the
- * parent process will use the shutdown_pending and restart_pending variables
- * to determine whether to shutdown or restart. The child process should
- * call signal_parent() directly to tell the parent to die -- this will
- * cause neither of those variable to be set, which the parent will
- * assume means something serious is wrong (which it will be, for the
- * child to force an exit) and so do an exit anyway.
- */
-
-void ap_start_shutdown(void)
-{
- if (shutdown_pending == 1) {
- /* Um, is this _probably_ not an error, if the user has
- * tried to do a shutdown twice quickly, so we won't
- * worry about reporting it.
- */
- return;
- }
- shutdown_pending = 1;
-}
-
-/* do a graceful restart if graceful == 1 */
-void ap_start_restart(int graceful)
-{
-
- if (restart_pending == 1) {
- /* Probably not an error - don't bother reporting it */
- return;
- }
- restart_pending = 1;
- is_graceful = graceful;
-}
-
-static void sig_term(int sig)
-{
- ap_start_shutdown();
-}
-
-static void restart(int sig)
-{
- ap_start_restart(1);
-}
-
-
/*
@@ -232,7 +142,6 @@ static void signal_parent(int type)
* to die, or for a signal on the "spache-signal" event. So set the
* "apache-signal" event here.
*/
-
if (one_process) {
return;
}
@@ -243,8 +152,6 @@ static void signal_parent(int type)
default: return;
}
-// APD2("signal_parent signalling event \"%s\"", signal_name);
-
e = OpenEvent(EVENT_ALL_ACCESS, FALSE, signal_name);
if (!e) {
/* Um, problem, can't signal the parent, which means we can't
@@ -263,38 +170,24 @@ static void signal_parent(int type)
}
CloseHandle(e);
}
-
-
-/*****************************************************************
- * Here follows a long bunch of generic server bookkeeping stuff...
- */
-
-static void sock_disable_nagle(int s) /* ZZZ abstract */
+void ap_start_shutdown(void)
{
- /* The Nagle algorithm says that we should delay sending partial
- * packets in hopes of getting more data. We don't want to do
- * this; we are not telnet. There are bad interactions between
- * persistent connections and Nagle's algorithm that have very severe
- * performance penalties. (Failing to disable Nagle is not much of a
- * problem with simple HTTP.)
- *
- * In spite of these problems, failure here is not a shooting offense.
- */
- int just_say_no = 1;
-
- if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
- sizeof(int)) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
- "setsockopt: (TCP_NODELAY)");
- }
+ signal_parent(0);
+}
+void ap_start_restart(int graceful)
+{
+ signal_parent(1);
}
+static int volatile is_graceful = 0;
API_EXPORT(int) ap_graceful_stop_signalled(void)
{
- /* XXX - Does this really work? - Manoj */
return is_graceful;
}
+/*
+ * Routines that deal with sockets, some are WIN32 specific...
+ */
static int s_iInitCount = 0;
static int AMCSocketInitialize(void)
{
@@ -327,8 +220,6 @@ static int AMCSocketInitialize(void)
return (s_iInitCount);
}
-
-
static void AMCSocketCleanup(void)
{
if (--s_iInitCount == 0)
@@ -336,10 +227,33 @@ static void AMCSocketCleanup(void)
return;
}
+static void sock_disable_nagle(int s) /* ZZZ abstract */
+{
+ /* The Nagle algorithm says that we should delay sending partial
+ * packets in hopes of getting more data. We don't want to do
+ * this; we are not telnet. There are bad interactions between
+ * persistent connections and Nagle's algorithm that have very severe
+ * performance penalties. (Failing to disable Nagle is not much of a
+ * problem with simple HTTP.)
+ *
+ * In spite of these problems, failure here is not a shooting offense.
+ */
+ int just_say_no = 1;
+
+ if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no,
+ sizeof(int)) < 0) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "setsockopt: (TCP_NODELAY)");
+ }
+}
/*
- * Find a listener which is ready for accept(). This advances the
- * head_listener global.
+ * Routines to deal with managing the list of listening sockets...
+ * find_ready_listener()
+ * Finds a listener which is ready for accept(). This advances
+ * the head_listener global.
+ * setup_listeners()
+ * setup_inherited_listeners()
*/
static ap_listen_rec *head_listener;
static ap_inline ap_listen_rec *find_ready_listener(fd_set * main_fds)
@@ -525,13 +439,10 @@ static int setup_inherited_listeners(pool *p, server_rec *s)
* 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));
@@ -543,9 +454,9 @@ int service_init()
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.
@@ -621,8 +532,6 @@ int remove_job(void)
rv = WaitForMultipleObjects(2, hObjects, FALSE, INFINITE);
ap_assert(rv != WAIT_FAILED);
if (rv == WAIT_OBJECT_0 + 1) {
- /* thread_exit_now */
-// APD1("thread got exit now event");
return -1;
}
/* must be semaphore */
@@ -652,7 +561,7 @@ int remove_job(void)
}
/*
- * child_sub_main() - this is the main loop for the worker threads
+ * child_main() - this is the main loop for the worker threads
*
* Each thread runs within this function. They wait within remove_job()
* for a job to become available, then handle all the requests on that
@@ -670,62 +579,29 @@ int remove_job(void)
* accepted socket, instead of blocking on a mutex or select().
*/
-static void child_sub_main(int child_num)
+static void child_main(int child_num)
{
- NET_SIZE_T clen;
struct sockaddr sa_server;
struct sockaddr sa_client;
+ int len;
+ BUFF *conn_io;
+ conn_rec *current_conn;
+ ap_iol *iol;
+
pool *ptrans;
int requests_this_child = 0;
int csd = -1;
- ap_iol *iol;
- int srv = 0;
- int conn_id = 1;
- /* Note: current_conn used to be a defined at file scope as follows... Since the signal code is
- not being used in WIN32, make the variable local */
- // static APACHE_TLS conn_rec *volatile current_conn;
- conn_rec *current_conn;
ptrans = ap_make_sub_pool(pconf);
#if 0
- /* ZZZ scoreboard */
(void) ap_update_child_status(child_num, SERVER_READY, (request_rec *) NULL);
#endif
- /*
- * Setup the jump buffers so that we can return here after a timeout.
- */
-#if 0 /* ZZZ */
-#if defined(USE_LONGJMP)
- setjmp(jmpbuffer);
-#else
- sigsetjmp(jmpbuffer, 1);
-#endif
-#ifdef SIGURG
- signal(SIGURG, timeout);
-#endif
-#endif
-
while (1) {
- BUFF *conn_io;
-// request_rec *r;
-
- /*
- * (Re)initialize this child to a pre-connection state.
- */
-#if 0 /* ZZZ Alarms... */
- ap_set_callback_and_alarm(NULL, 0); /* Cancel any outstanding alarms */
-#endif
-#if 0 /* ZZZ what is this? It's not thread safe! */
- timeout_req = NULL; /* No request in progress */
-#endif
current_conn = NULL;
-
ap_clear_pool(ptrans);
-
#if 0
- /* ZZZ scoreboard */
(void) ap_update_child_status(child_num, SERVER_READY,
(request_rec *) NULL);
#endif
@@ -744,69 +620,46 @@ static void child_sub_main(int child_num)
* We now have a connection, so set it up with the appropriate
* socket options, file descriptors, and read/write buffers.
*/
-
- clen = sizeof(sa_server);
- if (getsockname(csd, &sa_server, &clen) < 0) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "getsockname");
+ len = sizeof(struct sockaddr);
+ if (getsockname(csd, &sa_server, &len)== SOCKET_ERROR) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "getsockname failed with error %d\n", WSAGetLastError());
continue;
}
- clen = sizeof(sa_client);
- if ((getpeername(csd, &sa_client, &clen)) < 0) {
- /* get peername will fail if the input isn't a socket */
- perror("getpeername");
+
+ len = sizeof(struct sockaddr);
+ if ((getpeername(csd, &sa_client, &len)) == SOCKET_ERROR) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf,
+ "getpeername failed with error %d\n", WSAGetLastError());
memset(&sa_client, '\0', sizeof(sa_client));
}
-
- sock_disable_nagle(csd);
#if 0
- /* ZZZ scoreboard */
(void) ap_update_child_status(child_num, SERVER_BUSY_READ,
- (request_rec *) NULL);
+ (request_rec *) NULL);
#endif
+ sock_disable_nagle(csd);
+
iol = win32_attach_socket(csd);
if (iol == NULL) {
- if (errno == EBADF) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
- "filedescriptor (%u) larger than FD_SETSIZE (%u) "
- "found, you probably need to rebuild Apache with a "
- "larger FD_SETSIZE", csd, FD_SETSIZE);
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
- "error attaching to socket");
- }
+ ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ "error attaching to socket");
close(csd);
- return;
+ continue;
}
conn_io = ap_bcreate(ptrans, B_RDWR);
-
ap_bpush_iol(conn_io, iol);
-
+
current_conn = ap_new_connection(ptrans, server_conf, conn_io,
(struct sockaddr_in *) &sa_client,
(struct sockaddr_in *) &sa_server,
- conn_id);
-
- ap_process_connection(current_conn);
- }
-}
+ child_num);
-
-void child_main(int child_num_arg)
-{
- /*
- * Only reason for this function, is to pass in
- * arguments to child_sub_main() on its stack so
- * that longjump doesn't try to corrupt its local
- * variables and I don't need to make those
- * damn variables static/global
- */
- child_sub_main(child_num_arg);
+ ap_process_connection(current_conn);
+ }
}
-
-void cleanup_thread(thread **handles, int *thread_cnt, int thread_to_clean)
+static void cleanup_thread(thread **handles, int *thread_cnt, int thread_to_clean)
{
int i;
@@ -882,16 +735,18 @@ static void setup_signal_names(char *prefix)
* worker_main() is main loop for the child process. The loop in
* this function becomes the controlling thread for the actually working
* threads (which run in a loop in child_sub_main()).
+ * Globals Used:
+ * exit_event, start_mutex, ap_threads_per_child, server_conf,
+ * h_errno defined to WSAGetLastError in winsock2.h,
*/
-
-void worker_main(void)
+static void worker_main(void)
{
- int nthreads;
+ int nthreads = ap_threads_per_child;
fd_set main_fds;
int srv;
int clen;
int csd;
- int sd = -1; // made this local and not global
+ int sd = -1;
struct sockaddr_in sa_client;
int total_jobs = 0;
thread **child_handles;
@@ -906,11 +761,11 @@ void worker_main(void)
pchild = ap_make_sub_pool(pconf);
- nthreads = ap_threads_per_child;
-
// ap_restart_time = time(NULL);
-// reinit_scoreboard(pconf);
+#if 0
+ reinit_scoreboard(pconf);
+#endif
/*
* Wait until we have permission to start accepting connections.
@@ -927,13 +782,17 @@ void worker_main(void)
"Waiting for start_mutex or exit_event -- process will exit");
ap_destroy_pool(pchild);
-// cleanup_scoreboard();
+#if 0
+ cleanup_scoreboard();
+#endif
exit(0);
}
if (rv == WAIT_OBJECT_0 + 1) {
/* exit event signalled - exit now */
ap_destroy_pool(pchild);
-// cleanup_scoreboard();
+#if 0
+ cleanup_scoreboard();
+#endif
exit(0);
}
/* start_mutex obtained, continue into the select() loop */
@@ -952,10 +811,11 @@ void worker_main(void)
signal_parent(0); /* tell parent to die */
ap_destroy_pool(pchild);
-// cleanup_scoreboard();
+#if 0
+ cleanup_scoreboard();
+#endif
exit(0);
}
-// set_signals();
allowed_globals.jobsemaphore = create_semaphore(0);
allowed_globals.jobmutex = ap_create_mutex(NULL);
@@ -968,8 +828,6 @@ void worker_main(void)
while (1) {
if (ap_max_requests_per_child && (total_jobs > ap_max_requests_per_child)) {
- /* MaxRequestsPerChild hit...
- */
break;
}
/* Always check for the exit event being signaled.
@@ -977,7 +835,6 @@ void worker_main(void)
rv = WaitForSingleObject(exit_event, 0);
ap_assert((rv == WAIT_TIMEOUT) || (rv == WAIT_OBJECT_0));
if (rv == WAIT_OBJECT_0) {
-// APD1("child: exit event signalled, exiting");
break;
}
@@ -987,19 +844,16 @@ void worker_main(void)
memcpy(&main_fds, &listenfds, sizeof(fd_set));
srv = ap_select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
if (srv == SOCKET_ERROR) {
- /* Map the Win32 error into a standard Unix error condition */
- errno = WSAGetLastError();
-
/* Error occurred - if EINTR, loop around with problem */
- if (errno != EINTR) {
+ if (WSAGetLastError() != WSAEINTR) {
/* A "real" error occurred, log it and increment the count of
* select errors. This count is used to ensure we don't go into
* a busy loop of continuous errors.
*/
- ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "select: (listen)");
+ ap_log_error(APLOG_MARK, APLOG_INFO|APLOG_WIN32ERROR, server_conf, "select: (listen)");
count_select_errors++;
if (count_select_errors > MAX_SELECT_ERRORS) {
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, server_conf,
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
"Too many errors in select loop. Child process exiting.");
break;
}
@@ -1022,20 +876,14 @@ void worker_main(void)
csd = accept(sd, (struct sockaddr *) &sa_client, &clen);
if (csd == INVALID_SOCKET) {
csd = -1;
- errno = WSAGetLastError();
}
- } while (csd < 0 && errno == EINTR);
+ } while (csd < 0 && h_errno == WSAEINTR);
if (csd < 0) {
-#if defined(EPROTO) && defined(ECONNABORTED)
- if ((errno != EPROTO) && (errno != ECONNABORTED))
-#elif defined(EPROTO)
- if (errno != EPROTO)
-#elif defined(ECONNABORTED)
- if (errno != ECONNABORTED)
-#endif
- ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
+ if (h_errno != WSAECONNABORTED) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, server_conf,
"accept: (client socket)");
+ }
}
else {
add_job(csd);
@@ -1043,8 +891,6 @@ void worker_main(void)
}
}
-// APD2("process PID %d exiting", my_pid);
-
/* Get ready to shutdown and exit */
allowed_globals.exit_now = 1;
ap_release_mutex(start_mutex);
@@ -1057,7 +903,6 @@ void worker_main(void)
}
#endif
-// APD2("process PID %d waiting for worker threads to exit", my_pid);
/* Wait for all your children */
end_time = time(NULL) + 180;
while (nthreads) {
@@ -1072,7 +917,6 @@ void worker_main(void)
break;
}
-// APD2("process PID %d killing remaining worker threads", my_pid);
for (i = 0; i < nthreads; i++) {
kill_thread(child_handles[i]);
free_thread(child_handles[i]);
@@ -1085,11 +929,11 @@ void worker_main(void)
ap_destroy_pool(pchild);
-// cleanup_scoreboard();
+#if 0
+ cleanup_scoreboard();
+#endif
-// APD2("process PID %d exited", my_pid);
-// clean_parent_exit(0);
-} /* standalone_main */
+}
/*
* Spawn a child Apache process. The child process has the command line arguments from
@@ -1134,102 +978,98 @@ static void cleanup_process(HANDLE *handles, HANDLE *events, int position, int *
events[i] = events[i + 1];
}
(*processes)--;
-
-// 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 rv;
- char buf[1024];
- char *pCommand;
-
- STARTUPINFO si; /* Filled in prior to call to CreateProcess */
- PROCESS_INFORMATION pi; /* filled in on call to CreateProces */
-
- ap_listen_rec *lr;
- DWORD BytesWritten;
- HANDLE hPipeRead = NULL;
- HANDLE hPipeWrite = NULL;
- SECURITY_ATTRIBUTES sa = {0};
-
- 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_WIN32ERROR | APLOG_CRIT, server_conf,
- "Parent: Path to Apache process too long");
- return -1;
- } else if (rv == 0) {
- ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
- "Parent: GetModuleFileName() returned NULL for current 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);
-
- /* Create a pipe to send socket info to the child */
- if (!CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0)) {
- ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
- "Parent: Unable to create pipe to child process.\n");
- return -1;
- }
-
- SetEnvironmentVariable("AP_PARENT_PID",ap_psprintf(p,"%d",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.
- */
- 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 */
- NULL, /* Environment block */
- NULL,
- &si, &pi)) {
- ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, 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;
- }
- 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);
-
- SetEnvironmentVariable("AP_PARENT_PID",NULL);
-
- /* Create the exit_event, apCHILD_PID */
- kill_event = CreateEvent(NULL, TRUE, FALSE,
- ap_psprintf(pconf,"apC%d", pi.dwProcessId)); // 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");
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return -1;
+{
+ int rv;
+ char buf[1024];
+ char *pCommand;
+
+ STARTUPINFO si; /* Filled in prior to call to CreateProcess */
+ PROCESS_INFORMATION pi; /* filled in on call to CreateProces */
+
+ ap_listen_rec *lr;
+ DWORD BytesWritten;
+ HANDLE hPipeRead = NULL;
+ HANDLE hPipeWrite = NULL;
+ SECURITY_ATTRIBUTES sa = {0};
+
+ 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_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Path to Apache process too long");
+ return -1;
+ } else if (rv == 0) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: GetModuleFileName() returned NULL for current 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);
+
+ /* Create a pipe to send socket info to the child */
+ if (!CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, server_conf,
+ "Parent: Unable to create pipe to child process.\n");
+ return -1;
+ }
+
+ SetEnvironmentVariable("AP_PARENT_PID",ap_psprintf(p,"%d",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.
+ */
+ 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 */
+ NULL, /* Environment block */
+ NULL,
+ &si, &pi)) {
+ ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, 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;
+ }
+ 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);
+
+ SetEnvironmentVariable("AP_PARENT_PID",NULL);
+
+ /* Create the exit_event, apCHILD_PID */
+ kill_event = CreateEvent(NULL, TRUE, FALSE,
+ ap_psprintf(pconf,"apC%d", pi.dwProcessId)); // 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");
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ return -1;
}
/* Assume the child process lives. Update the process and event tables */
@@ -1276,7 +1116,6 @@ static int create_process(pool *p, HANDLE *handles, HANDLE *events, int *process
/* To share the semaphores with other processes, we need a NULL ACL
* Code from MS KB Q106387
*/
-
static PSECURITY_ATTRIBUTES GetNullACL()
{
PSECURITY_DESCRIPTOR pSD;
@@ -1421,7 +1260,6 @@ die_now:
int tmstart = time(NULL);
/* Signal each child processes to die */
for (i = 0; i < current_live_processes; i++) {
-// APD3("master_main: signalling child %d, handle %d to die", i, process_handles[i]);
if (SetEvent(process_kill_events[i]) == 0)
ap_log_error(APLOG_MARK,APLOG_ERR|APLOG_WIN32ERROR, server_conf,
"master_main: SetEvent for child process in slot #%d failed", i);
@@ -1444,7 +1282,7 @@ die_now:
return (0); /* Tell the caller we are shutting down */
}
- return (1); /* Tell the call we want a restart */
+ return (1); /* Tell the caller we want a restart */
}
/*
@@ -1457,7 +1295,6 @@ static void winnt_pre_config(pool *pconf, pool *plog, pool *ptemp)
/* Track parent/child pids... */
pid = getenv("AP_PARENT_PID");
- printf("pid = %d\n", pid);
if (pid) {
/* AP_PARENT_PID is only valid in the child */
parent_pid = atoi(pid);
@@ -1479,9 +1316,6 @@ static void winnt_pre_config(pool *pconf, pool *plog, pool *ptemp)
}
-/*
-Need to register this hook if we want it...
-*/
static void winnt_post_config(pool *pconf, pool *plog, pool *ptemp, server_rec* server_conf)
{
server_conf = server_conf;