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,
/*
*
*/
-static int get_scoreboard_from_parent(server_rec *s)
+void get_scoreboard_from_parent(server_rec *s)
{
apr_status_t rv;
HANDLE pipe;
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);
+
pipe = GetStdHandle(STD_INPUT_HANDLE);
if (!ReadFile(pipe, &sb_os_shm, sizeof(sb_os_shm),
&BytesRead, (LPOVERLAPPED) NULL)
|| (BytesRead != sizeof(sb_os_shm))) {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
- "child: Unable to access scoreboard handle from parent");
- ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
- exit(1);
+ "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))
!= APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
- "child: Unable to access scoreboard handle from parent");
- ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
- exit(1);
+ "Child %d: Unable to access the scoreboard from the parent", my_pid);
+ exit(APEXIT_CHILDINIT);
}
rv = ap_reopen_scoreboard(pchild, &ap_scoreboard_shm, 1);
if (rv || !(sb_shared = apr_shm_baseaddr_get(ap_scoreboard_shm))) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, "Looks like we're gonna die %d %x", rv, ap_scoreboard_shm);
- exit(APEXIT_INIT); /* XXX need to return an error from this function */
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
+ "Child %d: Unable to reopen the scoreboard from the parent", my_pid);
+ exit(APEXIT_CHILDINIT);
}
ap_init_scoreboard(sb_shared);
- return 1;
}
/*
* exclusively in the child process, receives them from the parent and
* makes them availeble in the child.
*/
-static int get_listeners_from_parent(server_rec *s)
+void get_listeners_from_parent(server_rec *s)
{
WSAPROTOCOL_INFO WSAProtocolInfo;
HANDLE pipe;
ap_listen_rec *lr;
DWORD BytesRead;
- int num_listeners = 0;
+ 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;
lr = apr_palloc(s->process->pool, sizeof(ap_listen_rec));
- if (!lr)
- return 0;
lr->sd = NULL;
lr->next = ap_listeners;
ap_listeners = lr;
*/
pipe = GetStdHandle(STD_INPUT_HANDLE);
- for (lr = ap_listeners; lr; lr = lr->next) {
+ for (lr = ap_listeners; lr; lr = lr->next, ++lcnt) {
if (!ReadFile(pipe, &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO),
&BytesRead, (LPOVERLAPPED) NULL)) {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
"setup_inherited_listeners: Unable to read socket data from parent");
- ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
- exit(1);
+ exit(APEXIT_CHILDINIT);
}
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, ap_server_conf,
- "Child %d: setup_inherited_listener() read = %d bytes of WSAProtocolInfo.", my_pid);
nsd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
&WSAProtocolInfo, 0, 0);
if (nsd == INVALID_SOCKET) {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), ap_server_conf,
"Child %d: setup_inherited_listeners(), WSASocket failed to open the inherited socket.", my_pid);
- ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
- exit(1);
+ exit(APEXIT_CHILDINIT);
}
apr_os_sock_put(&lr->sd, &nsd, pconf);
- num_listeners++;
}
CloseHandle(pipe);
if (!set_listeners_noninheritable(pconf)) {
- return 1;
+ exit(APEXIT_CHILDINIT);
}
- return num_listeners;
+ ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, 0, ap_server_conf,
+ "Child %d: retrieved %d listeners from parent", my_pid, lcnt);
}
if (status != APR_SUCCESS) {
ap_log_error(APLOG_MARK,APLOG_ERR, status, ap_server_conf,
"Child %d: Failed to acquire the start_mutex. Process will exit.", my_pid);
- ap_signal_parent(SIGNAL_PARENT_SHUTDOWN);
- exit(0);
+ exit(APEXIT_CHILDINIT);
}
ap_log_error(APLOG_MARK,APLOG_INFO, APR_SUCCESS, ap_server_conf,
"Child %d: Acquired the start mutex.", my_pid);
CloseHandle(exit_event);
}
+static int send_scoreboard_to_child(apr_pool_t *p, HANDLE hProcess, HANDLE hPipeWrite)
+{
+ apr_status_t rv;
+ HANDLE sb_os_shm;
+ HANDLE dup_os_shm;
+ HANDLE hCurrentProcess = GetCurrentProcess();
+ DWORD BytesWritten;
+
+ if ((rv = apr_os_shm_get(&sb_os_shm, ap_scoreboard_shm)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
+ "Parent: Unable to retrieve the scoreboard handle");
+ return -1;
+ }
+ if (!DuplicateHandle(hCurrentProcess, sb_os_shm, hProcess, &dup_os_shm,
+ 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),
+ &BytesWritten, (LPOVERLAPPED) NULL)
+ || (BytesWritten != sizeof(dup_os_shm))) {
+ 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 scoreboard to the child");
+ return 0;
+}
+
+static int send_listeners_to_child(apr_pool_t *p, DWORD dwProcessId, HANDLE hPipeWrite)
+{
+ int lcnt = 0;
+ ap_listen_rec *lr;
+ LPWSAPROTOCOL_INFO lpWSAProtocolInfo;
+ DWORD BytesWritten;
+
+ /* 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, ++lcnt) {
+ 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, ap_server_conf,
+ "Parent: Duplicating socket %d and sending it to child process %d",
+ nsd, dwProcessId);
+ if (WSADuplicateSocket(nsd, dwProcessId,
+ lpWSAProtocolInfo) == SOCKET_ERROR) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_netos_error(), ap_server_conf,
+ "Parent: WSADuplicateSocket failed for socket %d. Check the FAQ.", lr->sd );
+ return -1;
+ }
+
+ if (!WriteFile(hPipeWrite, lpWSAProtocolInfo, (DWORD) sizeof(WSAPROTOCOL_INFO),
+ &BytesWritten,
+ (LPOVERLAPPED) NULL)
+ || BytesWritten != sizeof(WSAPROTOCOL_INFO)) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
+ "Parent: Unable to write duplicated socket %d to the child.", lr->sd );
+ 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);
+ return 0;
+}
+
static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_event)
{
int rv;
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;
HANDLE hPipeWrite;
HANDLE hPipeWriteDup;
HANDLE hShareError;
HANDLE hShareErrorDup;
HANDLE hCurrentProcess = GetCurrentProcess();
- HANDLE sb_os_shm;
- HANDLE dup_os_shm;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
- LPWSAPROTOCOL_INFO lpWSAProtocolInfo;
-
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
si.hStdOutput = hNullOutput;
si.hStdError = hShareError;
- if (!CreateProcess(NULL, pCommand, NULL, NULL,
+ rv = CreateProcess(NULL, pCommand, NULL, NULL,
TRUE, /* Inherit handles */
CREATE_SUSPENDED, /* Creation flags */
pEnvBlock, /* Environment block */
NULL,
- &si, &pi)) {
+ &si, &pi);
+
+ /* Undo everything we created for the child only
+ */
+ CloseHandle(hPipeRead);
+ CloseHandle(hNullOutput);
+ CloseHandle(hShareError);
+ _putenv("AP_PARENT_PID=");
+ _putenv("AP_MY_GENERATION=");
+
+ if (!rv) {
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_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.
- */
+ "Parent: Failed to create the child process.");
CloseHandle(hPipeWrite);
- CloseHandle(hPipeRead);
- CloseHandle(hNullOutput);
- CloseHandle(hShareError);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return -1;
}
- 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);
- SetEnvironmentVariable("AP_PARENT_PID",NULL);
- *child_proc = pi.hProcess;
-
/* Create the child_exit_event, apCchild_pid. */
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
*/
Sleep(1000);
- if ((rv = apr_os_shm_get(&sb_os_shm, ap_scoreboard_shm)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
- "Parent: Unable to retrieve the scoreboard handle");
- return -1;
- }
- if (!DuplicateHandle(hCurrentProcess, sb_os_shm, pi.hProcess, &dup_os_shm,
- 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),
- &BytesWritten, (LPOVERLAPPED) NULL)
- || (BytesWritten != sizeof(dup_os_shm))) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf,
- "Parent: Unable to send the scoreboard handle to the child");
+ if (send_scoreboard_to_child(p, pi.hProcess, hPipeWrite)) {
+ CloseHandle(hPipeWrite);
return -1;
}
- /* 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, ap_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(), ap_server_conf,
- "Parent: WSADuplicateSocket failed for socket %d. Check the FAQ.", 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(), ap_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, ap_server_conf,
- "Parent: BytesWritten = %d WSAProtocolInfo = %x20", BytesWritten, *lpWSAProtocolInfo);
+ if (send_listeners_to_child(p, pi.dwProcessId, hPipeWrite)) {
+ CloseHandle(hPipeWrite);
+ return -1;
}
CloseHandle(hPipeWrite);
+ *child_proc = pi.hProcess;
+
return 0;
}
}
else {
/* The child process exited prematurely due to a fatal error. */
- restart_pending = 1;
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, ap_server_conf,
- "Parent: CHILD PROCESS FAILED -- Restarting the child process.");
+ DWORD exitcode;
+ if (!GetExitCodeProcess(event_handles[CHILD_HANDLE], &exitcode)) {
+ /* HUH? We did exit, didn't we? */
+ exitcode = APEXIT_CHILDFATAL;
+ }
+ if ( exitcode == APEXIT_CHILDFATAL
+ || exitcode == APEXIT_CHILDINIT
+ || exitcode == APEXIT_INIT) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, ap_server_conf,
+ "Parent: child process exited with status %u -- Aborting.", exitcode);
+ }
+ else {
+ restart_pending = 1;
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, ap_server_conf,
+ "Parent: child process exited with status %u -- Restarting.", exitcode);
+ }
+ CloseHandle(event_handles[CHILD_HANDLE]);
event_handles[CHILD_HANDLE] = NULL;
++ap_my_generation;
}
rv = apr_get_os_error();
ap_log_error(APLOG_MARK,APLOG_CRIT, rv, NULL,
"Failed to get the path of Apache.exe");
- exit(1);
+ exit(APEXIT_INIT);
}
/* WARNING: There is an implict assumption here that the
* executable resides in ServerRoot or ServerRoot\bin
{
ap_log_error(APLOG_MARK,APLOG_ERR, 0, NULL,
"%s: Service is already installed.", service_name);
- exit(1);
+ exit(APEXIT_INIT);
}
}
else if (running_as_service)
{
ap_log_error(APLOG_MARK,APLOG_ERR, service_set, NULL,
"No installed service named \"%s\".", service_name);
- exit(1);
+ exit(APEXIT_INIT);
}
}
if (strcasecmp(signal_arg, "install") && service_set && service_set != SERVICE_UNSET)
{
ap_log_error(APLOG_MARK,APLOG_ERR, service_set, NULL,
"No installed service named \"%s\".", service_name);
- exit(1);
+ exit(APEXIT_INIT);
}
/* Track the args actually entered by the user.
ap_log_error(APLOG_MARK,APLOG_CRIT, service_to_start_success, NULL,
"%s: Unable to start the service manager.",
service_name);
- /* XXX: return HTTP_INTERNAL_SERVER_ERROR? */
- exit(1);
+ exit(APEXIT_INIT);
}
if (!strcasecmp(signal_arg, "uninstall")) {
static void winnt_child_init(apr_pool_t *pchild, struct server_rec *ap_server_conf)
{
- /* This is the child process or we are running in single process mode. */
+ /* 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 the listeners. */
- ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ap_server_conf,
- "getting listeners child_main, pid %d", my_pid);
get_listeners_from_parent(ap_server_conf);
ap_my_generation = atoi(getenv("AP_MY_GENERATION"));