#ifdef WIN32
-#define CORE_PRIVATE
#include "httpd.h"
#include "http_main.h"
#include "http_log.h"
* score by moving a handle down the pipe into the child's stdin.
*/
extern apr_shm_t *ap_scoreboard_shm;
-server_rec *ap_server_conf;
+
+/* ap_my_generation are used by the scoreboard code */
+ap_generation_t volatile ap_my_generation=0;
/* Definitions of WINNT MPM specific config globals */
static HANDLE shutdown_event; /* used to signal the parent to shutdown */
OSVERSIONINFO osver; /* VER_PLATFORM_WIN32_NT */
+/* set by child_main to STACK_SIZE_PARAM_IS_A_RESERVATION for NT >= 5.1 (XP/2003) */
+DWORD stack_res_flag;
+
static DWORD parent_pid;
DWORD my_pid;
+/* used by parent to signal the child to start and exit */
+apr_proc_mutex_t *start_mutex;
+HANDLE exit_event;
+
int ap_threads_per_child = 0;
-int use_acceptex = 1;
static int thread_limit = 0;
static int first_thread_limit = 0;
int winnt_mpm_state = AP_MPMQ_STARTING;
-/* ap_my_generation are used by the scoreboard code */
-ap_generation_t volatile ap_my_generation=0;
-
/* shared by service.c as global, although
* perhaps it should be private.
*/
apr_pool_t *pconf;
+/* on several occasions we don't have the global server context
+ * although it's needed for logging, etc.
+ */
+server_rec *ap_server_conf;
/* definitions from child.c */
void child_main(apr_pool_t *pconf);
-/* used by parent to signal the child to start and exit
- * NOTE: these are not sophisticated enough for multiple children
- * so they ultimately should not be shared with child.c
- */
-extern apr_proc_mutex_t *start_mutex;
-extern HANDLE exit_event;
-
/* Only one of these, the pipe from our parent, ment only for
* one child worker's consumption (not to be inherited!)
* XXX: decorate this name for the trunk branch, was left simplified
thread_limit = atoi(arg);
return NULL;
}
-static const char *set_disable_acceptex(cmd_parms *cmd, void *dummy, char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
- if (use_acceptex) {
- use_acceptex = 0;
- ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL,
- "Disabled use of AcceptEx() WinSock2 API");
- }
- return NULL;
-}
static const command_rec winnt_cmds[] = {
LISTEN_COMMANDS,
"Number of threads each child creates" ),
AP_INIT_TAKE1("ThreadLimit", set_thread_limit, NULL, RSRC_CONF,
"Maximum worker threads in a server for this run of Apache"),
-AP_INIT_NO_ARGS("Win32DisableAcceptEx", set_disable_acceptex, NULL, RSRC_CONF,
- "Disable use of the high performance AcceptEx WinSock2 API to work around buggy VPN or Firewall software"),
-
{ NULL }
};
"%s_restart", signal_name_prefix);
}
-int volatile is_graceful = 0;
-
-AP_DECLARE(int) ap_graceful_stop_signalled(void)
-{
- return is_graceful;
-}
-
AP_DECLARE(void) ap_signal_parent(ap_signal_parent_e type)
{
HANDLE e;
case SIGNAL_PARENT_RESTART:
case SIGNAL_PARENT_RESTART_GRACEFUL:
{
- is_graceful = 1;
SetEvent(restart_event);
break;
}
case SIGNAL_PARENT_RESTART_GRACEFUL:
{
signal_name = signal_restart_name;
- is_graceful = 1;
break;
}
default:
DWORD BytesRead;
int lcnt = 0;
SOCKET nsd;
+ HANDLE hProcess = GetCurrentProcess();
+ HANDLE dup;
/* Set up a default listener if necessary */
if (ap_listeners == NULL) {
"setup_inherited_listeners: Unable to read socket data from parent");
exit(APEXIT_CHILDINIT);
}
+
nsd = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
&WSAProtocolInfo, 0, 0);
if (nsd == INVALID_SOCKET) {
exit(APEXIT_CHILDINIT);
}
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
- HANDLE hProcess = GetCurrentProcess();
- HANDLE dup;
- if (DuplicateHandle(hProcess, (HANDLE) nsd, hProcess, &dup,
- 0, FALSE, DUPLICATE_SAME_ACCESS)) {
- closesocket(nsd);
- nsd = (SOCKET) dup;
- }
- }
- else {
- /* A different approach. Many users report errors such as
- * (32538)An operation was attempted on something that is not
- * a socket. : Parent: WSADuplicateSocket failed...
- *
- * This appears that the duplicated handle is no longer recognized
- * as a socket handle. SetHandleInformation should overcome that
- * problem by not altering the handle identifier. But this won't
- * work on 9x - it's unsupported.
- */
- if (!SetHandleInformation((HANDLE)nsd, HANDLE_FLAG_INHERIT, 0)) {
- ap_log_error(APLOG_MARK, APLOG_ERR, apr_get_os_error(), ap_server_conf,
- "set_listeners_noninheritable: SetHandleInformation failed.");
- }
+ if (DuplicateHandle(hProcess, (HANDLE) nsd, hProcess, &dup,
+ 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+ closesocket(nsd);
+ nsd = (SOCKET) dup;
}
+
apr_os_sock_put(&lr->sd, &nsd, s->process->pool);
}
/* These NEVER change for the lifetime of this parent
*/
static char **args = NULL;
- static char **env = NULL;
static char pidbuf[28];
apr_status_t rv;
HANDLE waitlist[2]; /* see waitlist_e */
char *cmd;
char *cwd;
+ char **env;
+ int envc;
apr_pool_create_ex(&ptemp, p, NULL, NULL);
/* Build the command line. Should look something like this:
- * C:/apache/bin/apache.exe -f ap_server_confname
+ * C:/apache/bin/httpd.exe -f ap_server_confname
* First, get the path to the executable...
*/
apr_procattr_create(&attr, ptemp);
return -1;
}
- if (!env)
- {
- /* Build the env array, only once since it won't change
- * for the lifetime of this parent process.
- */
- int envc;
- for (envc = 0; _environ[envc]; ++envc) {
- ;
- }
- env = malloc((envc + 2) * sizeof (char*));
- memcpy(env, _environ, envc * sizeof (char*));
- apr_snprintf(pidbuf, sizeof(pidbuf), "AP_PARENT_PID=%i", parent_pid);
- env[envc] = pidbuf;
- env[envc + 1] = NULL;
+ /* Build the env array */
+ for (envc = 0; _environ[envc]; ++envc) {
+ ;
}
+ env = apr_palloc(ptemp, (envc + 2) * sizeof (char*));
+ memcpy(env, _environ, envc * sizeof (char*));
+ apr_snprintf(pidbuf, sizeof(pidbuf), "AP_PARENT_PID=%i", parent_pid);
+ env[envc] = pidbuf;
+ env[envc + 1] = NULL;
rv = apr_proc_create(&new_child, cmd, args, env, attr, ptemp);
if (rv != APR_SUCCESS) {
{
/* Handle the following SCM aspects in this phase:
*
- * -k runservice [transition for WinNT, nothing for Win9x]
+ * -k runservice [transition in service context only]
* -k install
* -k config
* -k uninstall
apr_getopt_t *opt;
int running_as_service = 1;
int errout = 0;
+ apr_file_t *nullfile;
pconf = process->pconf;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osver);
+ /* We wish this was *always* a reservation, but sadly it wasn't so and
+ * we couldn't break a hard limit prior to NT Kernel 5.1
+ */
+ if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT
+ && ((osver.dwMajorVersion > 5)
+ || ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion > 0)))) {
+ stack_res_flag = STACK_SIZE_PARAM_IS_A_RESERVATION;
+ }
+
/* AP_PARENT_PID is only valid in the child */
pid = getenv("AP_PARENT_PID");
if (pid)
* We hold the return value so that we can die in pre_config
* after logging begins, and the failure can land in the log.
*/
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- apr_file_t *nullfile;
-
- if (!errout) {
- mpm_nt_eventlog_stderr_open(service_name, process->pool);
- }
- service_to_start_success = mpm_service_to_start(&service_name,
- process->pool);
- if (service_to_start_success == APR_SUCCESS) {
- service_set = APR_SUCCESS;
- }
+ if (!errout) {
+ mpm_nt_eventlog_stderr_open(service_name, process->pool);
+ }
+ service_to_start_success = mpm_service_to_start(&service_name,
+ process->pool);
+ if (service_to_start_success == APR_SUCCESS) {
+ service_set = APR_SUCCESS;
+ }
- /* Open a null handle to soak stdout in this process.
- * Windows service processes are missing any file handle
- * usable for stdin/out/err. This was the cause of later
- * trouble with invocations of apr_file_open_stdout()
- */
- if ((rv = apr_file_open(&nullfile, "NUL",
- APR_READ | APR_WRITE, APR_OS_DEFAULT,
- process->pool)) == APR_SUCCESS) {
- apr_file_t *nullstdout;
- if (apr_file_open_stdout(&nullstdout, process->pool)
- == APR_SUCCESS)
- apr_file_dup2(nullstdout, nullfile, process->pool);
- apr_file_close(nullfile);
- }
+ /* Open a null handle to soak stdout in this process.
+ * Windows service processes are missing any file handle
+ * usable for stdin/out/err. This was the cause of later
+ * trouble with invocations of apr_file_open_stdout()
+ */
+ if ((rv = apr_file_open(&nullfile, "NUL",
+ APR_READ | APR_WRITE, APR_OS_DEFAULT,
+ process->pool)) == APR_SUCCESS) {
+ apr_file_t *nullstdout;
+ if (apr_file_open_stdout(&nullstdout, process->pool)
+ == APR_SUCCESS)
+ apr_file_dup2(nullstdout, nullfile, process->pool);
+ apr_file_close(nullfile);
}
}
ap_exists_config_define("DEBUG"))
one_process = -1;
+ /* XXX: presume proper privilages; one nice thing would be
+ * a loud emit if running as "LocalSystem"/"SYSTEM" to indicate
+ * they should change to a user with write access to logs/ alone.
+ */
+ ap_sys_privileges_handlers(1);
+
if (!strcasecmp(signal_arg, "runservice")
- && (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
&& (service_to_start_success != APR_SUCCESS)) {
ap_log_error(APLOG_MARK,APLOG_CRIT, service_to_start_success, NULL,
"%s: Unable to start the service manager.",
}
}
- /* use_acceptex (enabled by default) is not available on Win9x.
- */
- if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
- use_acceptex = 0;
- }
-
ap_listen_pre_config();
thread_limit = DEFAULT_THREAD_LIMIT;
ap_threads_per_child = DEFAULT_THREADS_PER_CHILD;
ap_pid_fname = DEFAULT_PIDLOG;
ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
-#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
- ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
-#endif
+ ap_max_mem_free = APR_ALLOCATOR_MAX_FREE_UNLIMITED;
apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
}
CleanNullACL((void *)sa);
- /* Now that we are flying at 15000 feet...
- * wipe out the Win95 service console,
- * signal the SCM the WinNT service started, or
- * if not a service, setup console handlers instead.
- */
- if (!strcasecmp(signal_arg, "runservice"))
- {
- if (osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
- {
- rv = mpm_service_to_start(&service_name,
- s->process->pool);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK,APLOG_ERR, rv, ap_server_conf,
- "%s: Unable to start the service manager.",
- service_name);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- }
- }
- else /* ! -k runservice */
- {
- mpm_start_console_handler();
- }
-
/* Create the start mutex, as an unnamed object for security.
* Ths start mutex is used during a restart to prevent more than
* one child process from entering the accept loop at once.
return HTTP_INTERNAL_SERVER_ERROR;
}
}
+ /* Always reset our console handler to be the first, even on a restart
+ * because some modules (e.g. mod_perl) might have set a console
+ * handler to terminate the process.
+ */
+ if (strcasecmp(signal_arg, "runservice"))
+ mpm_start_console_handler();
}
else /* parent_pid != my_pid */
{