SOCKET nsd;
HANDLE hProcess = GetCurrentProcess();
- ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
- "set_listeners_noninheritable: Marking listeners.");
for (lr = ap_listeners; lr; lr = lr->next) {
apr_os_sock_get(&nsd,lr->sd);
if (!DuplicateHandle(hProcess, (HANDLE) nsd, hProcess, &dup, 0,
nsd = (SOCKET) dup;
apr_os_sock_put(&lr->sd, &nsd, p);
}
+
+ if (my_pid == parent_pid) {
+ ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
+ "Parent: Marking listeners non-inherited.");
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
+ "Child %d: Marking listeners non-inherited.", my_pid);
+ }
return 1;
}
/*
*
*/
-void get_scoreboard_from_parent(server_rec *s)
+void get_handles_from_parent(server_rec *s)
{
- apr_status_t rv;
HANDLE pipe;
- HANDLE sb_os_shm;
+ HANDLE hScore;
DWORD BytesRead;
void *sb_shared;
-
- ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
- "Child %d: Retrieving scoreboard from parent.", my_pid);
-
+ apr_status_t rv;
+
pipe = GetStdHandle(STD_INPUT_HANDLE);
- if (!ReadFile(pipe, &sb_os_shm, sizeof(sb_os_shm),
+ if (!ReadFile(pipe, &exit_event, sizeof(HANDLE),
+ &BytesRead, (LPOVERLAPPED) NULL)
+ || (BytesRead != sizeof(HANDLE))) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
+ "Child %d: Unable to retrieve the exit event from the parent", my_pid);
+ exit(APEXIT_CHILDINIT);
+ }
+
+ if (!ReadFile(pipe, &hScore, sizeof(hScore),
&BytesRead, (LPOVERLAPPED) NULL)
- || (BytesRead != sizeof(sb_os_shm))) {
+ || (BytesRead != sizeof(hScore))) {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
"Child %d: Unable to retrieve the scoreboard from the parent", my_pid);
exit(APEXIT_CHILDINIT);
}
- if ((rv = apr_os_shm_put(&ap_scoreboard_shm, &sb_os_shm, s->process->pool))
+
+ if ((rv = apr_os_shm_put(&ap_scoreboard_shm, &hScore, s->process->pool))
!= APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
"Child %d: Unable to access the scoreboard from the parent", my_pid);
exit(APEXIT_CHILDINIT);
}
ap_init_scoreboard(sb_shared);
+
+ ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
+ "Child %d: Retrieved our scoreboard from the parent.", my_pid);
}
/*
int lcnt = 0;
SOCKET nsd;
- ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
- "Child %d: getting listeners from parent", my_pid);
-
/* Set up a default listener if necessary */
if (ap_listeners == NULL) {
ap_listen_rec *lr;
}
apr_os_sock_put(&lr->sd, &nsd, pconf);
}
- CloseHandle(pipe);
+
+ ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
+ "Child %d: retrieved %d listeners from parent", my_pid, lcnt);
if (!set_listeners_noninheritable(pconf)) {
exit(APEXIT_CHILDINIT);
}
-
- ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
- "Child %d: retrieved %d listeners from parent", my_pid, lcnt);
}
apr_status_t status;
ap_listen_rec *lr;
HANDLE child_events[2];
- char* exit_event_name;
int nthreads = ap_threads_per_child;
int tid;
thread *child_handles;
apr_pool_create(&pchild, pconf);
- 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,
- APR_LOCK_DEFAULT, 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, ap_server_conf,
- "Child %d: exit_event_name = %s", my_pid, exit_event_name);
- }
-
ap_run_child_init(pchild, ap_server_conf);
- ap_assert(start_mutex);
- ap_assert(exit_event);
- ap_assert(max_requests_per_child_event);
-
/* Initialize the child_events */
max_requests_per_child_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!max_requests_per_child_event) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, status, ap_server_conf,
+ "Child %d: Failed to create a max_requests event.", my_pid);
+ exit(APEXIT_CHILDINIT);
+ }
child_events[0] = exit_event;
child_events[1] = max_requests_per_child_event;
CloseHandle(exit_event);
}
-static int send_scoreboard_to_child(apr_pool_t *p, HANDLE hProcess, HANDLE hPipeWrite)
+static int send_handles_to_child(apr_pool_t *p, HANDLE child_exit_event, HANDLE hProcess, HANDLE hPipeWrite)
{
apr_status_t rv;
- HANDLE sb_os_shm;
- HANDLE dup_os_shm;
+ HANDLE hScore;
+ HANDLE hDup;
HANDLE hCurrentProcess = GetCurrentProcess();
DWORD BytesWritten;
- if ((rv = apr_os_shm_get(&sb_os_shm, ap_scoreboard_shm)) != APR_SUCCESS) {
+ if (!DuplicateHandle(hCurrentProcess, child_exit_event, hProcess, &hDup,
+ 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
+ "Parent: Unable to duplicate the exit event handle for the child");
+ return -1;
+ }
+ if (!WriteFile(hPipeWrite, &hDup, sizeof(hDup),
+ &BytesWritten, (LPOVERLAPPED) NULL)
+ || (BytesWritten != sizeof(hDup))) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
+ "Parent: Unable to send the exit event handle to the child");
+ return -1;
+ }
+
+ if ((rv = apr_os_shm_get(&hScore, ap_scoreboard_shm)) != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
- "Parent: Unable to retrieve the scoreboard handle");
+ "Parent: Unable to retrieve the scoreboard handle for the child");
return -1;
}
- if (!DuplicateHandle(hCurrentProcess, sb_os_shm, hProcess, &dup_os_shm,
+ if (!DuplicateHandle(hCurrentProcess, hScore, hProcess, &hDup,
0, FALSE, DUPLICATE_SAME_ACCESS)) {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
"Parent: Unable to duplicate the scoreboard handle to the child");
return -1;
}
- if (!WriteFile(hPipeWrite, &dup_os_shm, sizeof(dup_os_shm),
+ if (!WriteFile(hPipeWrite, &hDup, sizeof(hDup),
&BytesWritten, (LPOVERLAPPED) NULL)
- || (BytesWritten != sizeof(dup_os_shm))) {
+ || (BytesWritten != sizeof(hDup))) {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
"Parent: Unable to send the scoreboard handle to the child");
return -1;
}
ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
- "Parent: Sent the %d listeners to child %d", lcnt, dwProcessId);
+ "Parent: Sent %d listeners to child %d", lcnt, dwProcessId);
return 0;
}
int iEnvBlockLen;
STARTUPINFO si; /* Filled in prior to call to CreateProcess */
PROCESS_INFORMATION pi; /* filled in on call to CreateProcess */
-
+ HANDLE hDup;
HANDLE hPipeRead;
HANDLE hPipeWrite;
- HANDLE hPipeWriteDup;
HANDLE hNullOutput;
HANDLE hShareError;
- HANDLE hShareErrorDup;
HANDLE hCurrentProcess = GetCurrentProcess();
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
pCommand = apr_pstrcat(p, pCommand, " \"", ap_server_conf->process->argv[i], "\"", NULL);
}
- /*
- * Build the environment
- * Win32's CreateProcess call requires that the environment
- * be passed in an environment block, a null terminated block of
- * null terminated strings.
- */
- _putenv(apr_psprintf(p,"AP_PARENT_PID=%i", parent_pid));
- _putenv(apr_psprintf(p,"AP_MY_GENERATION=%i", ap_my_generation));
-
- i = 0;
- iEnvBlockLen = 1;
- while (_environ[i]) {
- iEnvBlockLen += strlen(_environ[i]) + 1;
- i++;
- }
- pEnvBlock = (char *)apr_pcalloc(p, iEnvBlockLen);
- pEnvVar = pEnvBlock;
- 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(), ap_server_conf,
/* Make our end of the handle non-inherited */
if (DuplicateHandle(hCurrentProcess, hPipeWrite, hCurrentProcess,
- &hPipeWriteDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+ &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
CloseHandle(hPipeWrite);
- hPipeWrite = hPipeWriteDup;
+ hPipeWrite = hDup;
}
else {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
"Parent: Unable to duplicate pipe to child.\n");
+ CloseHandle(hPipeWrite);
+ CloseHandle(hPipeRead);
+ return -1;
}
/* Open a null handle to soak info from the child */
if (hNullOutput == INVALID_HANDLE_VALUE) {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
"Parent: Unable to create null output pipe for child process.\n");
+ CloseHandle(hPipeWrite);
+ CloseHandle(hPipeRead);
+ return -1;
}
/* Child's initial stderr -> our main server error log (or, failing that, stderr) */
rv = apr_os_file_get(&hShareError, ap_server_conf->error_log);
if (rv == APR_SUCCESS && hShareError != INVALID_HANDLE_VALUE) {
if (DuplicateHandle(hCurrentProcess, hShareError,
- hCurrentProcess, &hShareErrorDup,
+ hCurrentProcess, &hDup,
0, TRUE, DUPLICATE_SAME_ACCESS)) {
- hShareError = hShareErrorDup;
+ hShareError = hDup;
}
else {
rv = apr_get_os_error();
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
"Parent: Unable to share error log with child.\n");
+ CloseHandle(hPipeWrite);
+ CloseHandle(hPipeRead);
+ CloseHandle(hNullOutput);
+ return -1;
}
else if (hShareError == INVALID_HANDLE_VALUE) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, 0, ap_server_conf,
"Parent: Failed to share error log with child.\n");
+ CloseHandle(hPipeWrite);
+ CloseHandle(hPipeRead);
+ CloseHandle(hNullOutput);
+ return -1;
}
else {
hShareError = GetStdHandle(STD_ERROR_HANDLE);
}
+ /* Create the child_exit_event */
+ *child_exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!(*child_exit_event)) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
+ "Parent: Could not create exit event for child process");
+ CloseHandle(hPipeWrite);
+ CloseHandle(hPipeRead);
+ CloseHandle(hNullOutput);
+ CloseHandle(hShareError);
+ return -1;
+ }
+
+ /*
+ * Build the environment
+ * Win32's CreateProcess call requires that the environment
+ * be passed in an environment block, a null terminated block of
+ * null terminated strings.
+ */
+ _putenv(apr_psprintf(p,"AP_PARENT_PID=%i", parent_pid));
+ _putenv(apr_psprintf(p,"AP_MY_GENERATION=%i", ap_my_generation));
+
+ i = 0;
+ iEnvBlockLen = 1;
+ while (_environ[i]) {
+ iEnvBlockLen += strlen(_environ[i]) + 1;
+ i++;
+ }
+ pEnvBlock = (char *)apr_pcalloc(p, iEnvBlockLen);
+ pEnvVar = pEnvBlock;
+ i = 0;
+ while (_environ[i]) {
+ strcpy(pEnvVar, _environ[i]);
+ pEnvVar = strchr(pEnvVar, '\0') + 1;
+ i++;
+ }
+ pEnvVar = '\0';
+
/* 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.
*/
rv = CreateProcess(NULL, pCommand, NULL, NULL,
TRUE, /* Inherit handles */
- CREATE_SUSPENDED, /* Creation flags */
+ 0, /* Creation flags */
pEnvBlock, /* Environment block */
NULL,
&si, &pi);
/* Undo everything we created for the child only
*/
+ CloseHandle(pi.hThread);
CloseHandle(hPipeRead);
CloseHandle(hNullOutput);
CloseHandle(hShareError);
ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf,
"Parent: Created child process %d", pi.dwProcessId);
- /* Create the child_exit_event, apCchild_pid. */
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- *child_exit_event = CreateEvent(&sa, TRUE, FALSE, apr_psprintf(pconf,"apC%d", pi.dwProcessId));
- if (!(*child_exit_event)) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
- "Parent: Could not create exit event for child process");
- CloseHandle(hPipeWrite);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return -1;
- }
-
- ResumeThread(pi.hThread);
- CloseHandle(pi.hThread);
-
/* Important:
* Give the child process a chance to run before dup'ing the sockets.
* We have already set the listening sockets noninheritable, but if
*/
Sleep(1000);
- if (send_scoreboard_to_child(p, pi.hProcess, hPipeWrite)) {
+ if (send_handles_to_child(p, *child_exit_event, pi.hProcess, hPipeWrite)) {
CloseHandle(hPipeWrite);
return -1;
}
static void winnt_child_init(apr_pool_t *pchild, struct server_rec *ap_server_conf)
{
+ setup_signal_names(apr_psprintf(pchild,"ap%d", parent_pid));
+
/* This is a child process, not in single process mode */
if (!one_process) {
- /* Set up the scoreboard. */
- get_scoreboard_from_parent(ap_server_conf);
+ /* Set up events and the scoreboard */
+ get_handles_from_parent(ap_server_conf);
- /* Set up the listeners. */
+ /* Set up the listeners */
get_listeners_from_parent(ap_server_conf);
ap_my_generation = atoi(getenv("AP_MY_GENERATION"));
+
+ apr_lock_child_init(&start_mutex, signal_name_prefix, pconf);
+ DebugBreak();
+ }
+ else {
+ /* Single process mode - this lock doesn't even need to exist */
+ apr_lock_create(&start_mutex, APR_MUTEX, APR_CROSS_PROCESS,
+ APR_LOCK_DEFAULT, signal_name_prefix, pconf);
+
+ /* Borrow the shutdown_even as our _child_ loop exit event */
+ exit_event = shutdown_event;
}
}