summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:13 +0100
committerStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:13 +0100
commit1acac7a6b494db24f8f58e44dab7657b6de68742 (patch)
tree9a0dd3753dd6fb8c859ed299ee9794b88173c420 /server
parent80ba9f34b69a273d82f2f46d7fe231e30e127028 (diff)
downloadapache2-1acac7a6b494db24f8f58e44dab7657b6de68742.tar.gz
Upstream tarball 2.2.6upstream/2.2.6
Diffstat (limited to 'server')
-rw-r--r--server/NWGNUmakefile6
-rw-r--r--server/core.c2
-rw-r--r--server/log.c95
-rw-r--r--server/main.c39
-rw-r--r--server/mpm/experimental/event/event.c10
-rw-r--r--server/mpm/experimental/event/fdqueue.c3
-rw-r--r--server/mpm/netware/mpm_netware.c10
-rw-r--r--server/mpm/prefork/prefork.c14
-rw-r--r--server/mpm/winnt/Win9xConHook.dsp12
-rw-r--r--server/mpm/winnt/mpm_winnt.c114
-rw-r--r--server/mpm/worker/fdqueue.c3
-rw-r--r--server/mpm/worker/worker.c10
-rw-r--r--server/mpm_common.c72
-rw-r--r--server/request.c5
-rw-r--r--server/util.c7
15 files changed, 291 insertions, 111 deletions
diff --git a/server/NWGNUmakefile b/server/NWGNUmakefile
index f2f6da75..512adfdc 100644
--- a/server/NWGNUmakefile
+++ b/server/NWGNUmakefile
@@ -102,7 +102,7 @@ NLM_NAME = genchars
# This is used by the link '-desc ' directive.
# If left blank, NLM_NAME will be used.
#
-NLM_DESCRIPTION = Generate Test Characters
+NLM_DESCRIPTION = Apache $(VERSION_STR) Generate Test Characters
#
# This is used by the '-threadname' directive. If left blank,
@@ -112,9 +112,9 @@ NLM_THREAD_NAME = genchars
#
# If this is specified, it will override VERSION value in
-# $(AP_WORK)\NWGNUNetWare.rul
+# $(AP_WORK)\build\NWGNUenvironment.inc
#
-NLM_VERSION = 1,0,0
+NLM_VERSION =
#
# If this is specified, it will override the default of 64K
diff --git a/server/core.c b/server/core.c
index 69cd3dcb..b4aca33b 100644
--- a/server/core.c
+++ b/server/core.c
@@ -417,7 +417,7 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
conf->etag_add =
(conf->etag_add & (~ new->etag_remove)) | new->etag_add;
conf->etag_remove =
- (conf->opts_remove & (~ new->etag_add)) | new->etag_remove;
+ (conf->etag_remove & (~ new->etag_add)) | new->etag_remove;
conf->etag_bits =
(conf->etag_bits & (~ conf->etag_remove)) | conf->etag_add;
}
diff --git a/server/log.c b/server/log.c
index c027f002..14b4fdc2 100644
--- a/server/log.c
+++ b/server/log.c
@@ -139,6 +139,8 @@ static const TRANS priorities[] = {
{NULL, -1},
};
+static apr_pool_t *stderr_pool = NULL;
+
static apr_file_t *stderr_log = NULL;
/* track pipe handles to close in child process */
@@ -151,7 +153,7 @@ static read_handle_t *read_handles;
/* clear_handle_list() is called when plog is cleared; at that
* point we need to forget about our old list of pipe read
- * handles
+ * handles. We let the plog cleanups close the actual pipes.
*/
static apr_status_t clear_handle_list(void *v)
{
@@ -205,15 +207,36 @@ AP_DECLARE(apr_status_t) ap_replace_stderr_log(apr_pool_t *p,
ap_server_argv0, fname);
return rc;
}
- if ((rc = apr_file_open_stderr(&stderr_log, p)) == APR_SUCCESS) {
+ if (!stderr_pool) {
+ /* This is safe provided we revert it when we are finished.
+ * We don't manager the callers pool!
+ */
+ stderr_pool = p;
+ }
+ if ((rc = apr_file_open_stderr(&stderr_log, stderr_pool))
+ == APR_SUCCESS) {
apr_file_flush(stderr_log);
- if ((rc = apr_file_dup2(stderr_log, stderr_file, p)) == APR_SUCCESS) {
+ if ((rc = apr_file_dup2(stderr_log, stderr_file, stderr_pool))
+ == APR_SUCCESS) {
apr_file_close(stderr_file);
+ /*
+ * You might ponder why stderr_pool should survive?
+ * The trouble is, stderr_pool may have s_main->error_log,
+ * so we aren't in a position to destory stderr_pool until
+ * the next recycle. There's also an apparent bug which
+ * is not; if some folk decided to call this function before
+ * the core open error logs hook, this pool won't survive.
+ * Neither does the stderr logger, so this isn't a problem.
+ */
}
}
+ /* Revert, see above */
+ if (stderr_pool == p)
+ stderr_pool = NULL;
+
if (rc != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rc, NULL,
- "unable to replace stderr with error_log");
+ "unable to replace stderr with error log file");
}
return rc;
}
@@ -250,18 +273,20 @@ static int log_child(apr_pool_t *p, const char *progname,
APR_NO_PIPE,
APR_NO_PIPE)) == APR_SUCCESS)
&& ((rc = apr_procattr_error_check_set(procattr, 1)) == APR_SUCCESS)
- && ((rc = apr_procattr_child_errfn_set(procattr, log_child_errfn)) == APR_SUCCESS)
- && (!dummy_stderr
- || ((rc = apr_file_open_stdout(&errfile, p)) == APR_SUCCESS
- && (rc = apr_procattr_child_err_set(procattr,
- errfile,
- errfile)) == APR_SUCCESS))) {
+ && ((rc = apr_procattr_child_errfn_set(procattr, log_child_errfn))
+ == APR_SUCCESS)) {
char **args;
const char *pname;
apr_tokenize_to_argv(progname, &args, p);
pname = apr_pstrdup(p, args[0]);
procnew = (apr_proc_t *)apr_pcalloc(p, sizeof(*procnew));
+
+ if (dummy_stderr) {
+ if ((rc = apr_file_open_stdout(&errfile, p)) == APR_SUCCESS)
+ rc = apr_procattr_child_err_set(procattr, errfile, NULL);
+ }
+
rc = apr_proc_create(procnew, pname, (const char * const *)args,
NULL, procattr, p);
@@ -272,13 +297,6 @@ static int log_child(apr_pool_t *p, const char *progname,
* close_handle_in_child()
*/
}
-
- /* apr_procattr_child_err_set dups errfile twice: close the
- * remaining "parent-side" copy (apr_proc_create closes the
- * other). */
- if (dummy_stderr) {
- apr_file_close(procnew->err);
- }
}
return rc;
@@ -354,29 +372,54 @@ static int open_error_log(server_rec *s, int is_main, apr_pool_t *p)
int ap_open_logs(apr_pool_t *pconf, apr_pool_t *p /* plog */,
apr_pool_t *ptemp, server_rec *s_main)
{
- apr_status_t rc = APR_SUCCESS;
+ apr_pool_t *stderr_p;
server_rec *virt, *q;
int replace_stderr;
- apr_file_t *errfile = NULL;
+
+ /* Register to throw away the read_handles list when we
+ * cleanup plog. Upon fork() for the apache children,
+ * this read_handles list is closed so only the parent
+ * can relaunch a lost log child. These read handles
+ * are always closed on exec.
+ * We won't care what happens to our stderr log child
+ * between log phases, so we don't mind losing stderr's
+ * read_handle a little bit early.
+ */
apr_pool_cleanup_register(p, NULL, clear_handle_list,
apr_pool_cleanup_null);
- if (open_error_log(s_main, 1, p) != OK) {
+
+ /* HERE we need a stdout log that outlives plog.
+ * We *presume* the parent of plog is a process
+ * or global pool which spans server restarts.
+ * Create our stderr_pool as a child of the plog's
+ * parent pool.
+ */
+ apr_pool_create(&stderr_p, apr_pool_parent_get(p));
+ apr_pool_tag(stderr_p, "stderr_pool");
+
+ if (open_error_log(s_main, 1, stderr_p) != OK) {
return DONE;
}
replace_stderr = 1;
if (s_main->error_log) {
- /* replace stderr with this new log */
+ apr_status_t rv;
+
+ /* Replace existing stderr with new log. */
apr_file_flush(s_main->error_log);
- if ((rc = apr_file_open_stderr(&errfile, p)) == APR_SUCCESS) {
- rc = apr_file_dup2(errfile, s_main->error_log, p);
- }
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rc, s_main,
+ rv = apr_file_dup2(stderr_log, s_main->error_log, stderr_p);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s_main,
"unable to replace stderr with error_log");
}
else {
+ /* We are done with stderr_pool, close it, killing
+ * the previous generation's stderr logger
+ */
+ if (stderr_pool)
+ apr_pool_destroy(stderr_pool);
+ stderr_pool = stderr_p;
replace_stderr = 0;
}
}
diff --git a/server/main.c b/server/main.c
index 29557f23..22c0b683 100644
--- a/server/main.c
+++ b/server/main.c
@@ -20,6 +20,7 @@
#include "apr_general.h"
#include "apr_lib.h"
#include "apr_md5.h"
+#include "apr_time.h"
#include "apr_version.h"
#include "apu_version.h"
@@ -261,20 +262,29 @@ static void destroy_and_exit_process(process_rec *process,
exit(process_exit_value);
}
-static process_rec *create_process(int argc, const char * const *argv)
+static process_rec *init_process(int *argc, const char * const * *argv)
{
process_rec *process;
apr_pool_t *cntx;
apr_status_t stat;
+ const char *failed = "apr_app_initialize()";
+
+ stat = apr_app_initialize(argc, argv, NULL);
+ if (stat == APR_SUCCESS) {
+ failed = "apr_pool_create()";
+ stat = apr_pool_create(&cntx, NULL);
+ }
- stat = apr_pool_create(&cntx, NULL);
if (stat != APR_SUCCESS) {
- /* XXX From the time that we took away the NULL pool->malloc mapping
- * we have been unable to log here without segfaulting.
+ /* For all intents and purposes, this is impossibly unlikely,
+ * but APR doesn't exist yet, we can't use it for reporting
+ * these earliest two failures;
*/
- ap_log_error(APLOG_MARK, APLOG_ERR, stat, NULL,
- "apr_pool_create() failed to create "
- "initial context");
+ char ctimebuff[APR_CTIME_LEN];
+ apr_ctime(ctimebuff, apr_time_now());
+ fprintf(stderr, "[%s] [crit] (%d) %s: %s failed "
+ "to initial context, exiting\n",
+ ctimebuff, stat, (*argv)[0], failed);
apr_terminate();
exit(1);
}
@@ -282,14 +292,19 @@ static process_rec *create_process(int argc, const char * const *argv)
apr_pool_tag(cntx, "process");
ap_open_stderr_log(cntx);
+ /* Now we have initialized apr and our logger, no more
+ * exceptional error reporting required for the lifetime
+ * of this server process.
+ */
+
process = apr_palloc(cntx, sizeof(process_rec));
process->pool = cntx;
apr_pool_create(&process->pconf, process->pool);
apr_pool_tag(process->pconf, "pconf");
- process->argc = argc;
- process->argv = argv;
- process->short_name = apr_filepath_name_get(argv[0]);
+ process->argc = *argc;
+ process->argv = *argv;
+ process->short_name = apr_filepath_name_get((*argv)[0]);
return process;
}
@@ -442,9 +457,7 @@ int main(int argc, const char * const argv[])
AP_MONCONTROL(0); /* turn off profiling of startup */
- apr_app_initialize(&argc, &argv, NULL);
-
- process = create_process(argc, argv);
+ process = init_process(&argc, &argv);
pglobal = process->pool;
pconf = process->pconf;
ap_server_argv0 = process->short_name;
diff --git a/server/mpm/experimental/event/event.c b/server/mpm/experimental/event/event.c
index e105c25e..2a6913b3 100644
--- a/server/mpm/experimental/event/event.c
+++ b/server/mpm/experimental/event/event.c
@@ -1998,12 +1998,10 @@ int ap_mpm_run(apr_pool_t * _pconf, apr_pool_t * plog, server_rec * s)
active_children = 0;
for (index = 0; index < ap_daemons_limit; ++index) {
- if (MPM_CHILD_PID(index) != 0) {
- if (kill(MPM_CHILD_PID(index), 0) == 0) {
- active_children = 1;
- /* Having just one child is enough to stay around */
- break;
- }
+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
+ active_children = 1;
+ /* Having just one child is enough to stay around */
+ break;
}
}
} while (!shutdown_pending && active_children &&
diff --git a/server/mpm/experimental/event/fdqueue.c b/server/mpm/experimental/event/fdqueue.c
index 51952ced..c0ef9bbb 100644
--- a/server/mpm/experimental/event/fdqueue.c
+++ b/server/mpm/experimental/event/fdqueue.c
@@ -65,8 +65,7 @@ apr_status_t ap_queue_info_create(fd_queue_info_t ** queue_info,
apr_status_t rv;
fd_queue_info_t *qi;
- qi = apr_palloc(pool, sizeof(*qi));
- memset(qi, 0, sizeof(*qi));
+ qi = apr_pcalloc(pool, sizeof(*qi));
rv = apr_thread_mutex_create(&qi->idlers_mutex, APR_THREAD_MUTEX_DEFAULT,
pool);
diff --git a/server/mpm/netware/mpm_netware.c b/server/mpm/netware/mpm_netware.c
index a6f89633..a8d0952f 100644
--- a/server/mpm/netware/mpm_netware.c
+++ b/server/mpm/netware/mpm_netware.c
@@ -191,6 +191,14 @@ static void clean_child_exit(int code, int worker_num, apr_pool_t *ptrans,
NXThreadExit((void*)&code);
}
+/* proper cleanup when returning from ap_mpm_run() */
+static void mpm_main_cleanup(void)
+{
+ if (pmain) {
+ apr_pool_destroy(pmain);
+ }
+}
+
AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result)
{
switch(query_code){
@@ -934,6 +942,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
apr_thread_yield();
}
+ mpm_main_cleanup();
return 1;
}
else { /* the only other way out is a restart */
@@ -956,6 +965,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
printf ("\nRestarting...\n");
}
+ mpm_main_cleanup();
return 0;
}
diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
index ba50581b..d3c93a63 100644
--- a/server/mpm/prefork/prefork.c
+++ b/server/mpm/prefork/prefork.c
@@ -1127,7 +1127,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
for (index = 0; index < ap_daemons_limit; ++index) {
if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
/* Ask each child to close its listeners. */
- kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
+ ap_mpm_safe_kill(MPM_CHILD_PID(index), AP_SIG_GRACEFUL);
active_children++;
}
}
@@ -1165,12 +1165,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
active_children = 0;
for (index = 0; index < ap_daemons_limit; ++index) {
- if (MPM_CHILD_PID(index) != 0) {
- if (kill(MPM_CHILD_PID(index), 0) == 0) {
- active_children = 1;
- /* Having just one child is enough to stay around */
- break;
- }
+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
+ active_children = 1;
+ /* Having just one child is enough to stay around */
+ break;
}
}
} while (!shutdown_pending && active_children &&
@@ -1222,7 +1220,7 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
* piped loggers, etc. They almost certainly won't handle
* it gracefully.
*/
- kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
+ ap_mpm_safe_kill(ap_scoreboard_image->parent[index].pid, AP_SIG_GRACEFUL);
}
}
}
diff --git a/server/mpm/winnt/Win9xConHook.dsp b/server/mpm/winnt/Win9xConHook.dsp
index 77cbacfc..55bee020 100644
--- a/server/mpm/winnt/Win9xConHook.dsp
+++ b/server/mpm/winnt/Win9xConHook.dsp
@@ -54,6 +54,12 @@ BSC32=bscmake.exe
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /base:"0x1c0f0000"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /base:"0x1c0f0000" /opt:ref
+# Begin Special Build Tool
+TargetPath=.\Release\Win9xConHook.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
!ELSEIF "$(CFG)" == "Win9xConHook - Win32 Debug"
@@ -80,6 +86,12 @@ BSC32=bscmake.exe
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /base:"0x1c0f0000"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:no /debug /base:"0x1c0f0000"
+# Begin Special Build Tool
+TargetPath=.\Debug\Win9xConHook.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
!ENDIF
diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c
index e55cbb46..4b37d741 100644
--- a/server/mpm/winnt/mpm_winnt.c
+++ b/server/mpm/winnt/mpm_winnt.c
@@ -66,7 +66,6 @@ static int thread_limit = DEFAULT_THREAD_LIMIT;
static int first_thread_limit = 0;
static int changed_limit_at_restart;
int winnt_mpm_state = AP_MPMQ_STARTING;
-
/* ap_my_generation are used by the scoreboard code */
ap_generation_t volatile ap_my_generation=0;
@@ -87,6 +86,12 @@ void child_main(apr_pool_t *pconf);
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
+ * only to make the 2.2 patch trivial to read.
+ */
+static HANDLE pipe;
/* Stub functions until this MPM supports the connection status API */
@@ -330,7 +335,6 @@ void get_handles_from_parent(server_rec *s, HANDLE *child_exit_event,
apr_proc_mutex_t **child_start_mutex,
apr_shm_t **scoreboard_shm)
{
- HANDLE pipe;
HANDLE hScore;
HANDLE ready_event;
HANDLE os_start;
@@ -338,7 +342,9 @@ void get_handles_from_parent(server_rec *s, HANDLE *child_exit_event,
void *sb_shared;
apr_status_t rv;
- pipe = GetStdHandle(STD_INPUT_HANDLE);
+ /* *** We now do this was back in winnt_rewrite_args
+ * pipe = GetStdHandle(STD_INPUT_HANDLE);
+ */
if (!ReadFile(pipe, &ready_event, sizeof(HANDLE),
&BytesRead, (LPOVERLAPPED) NULL)
|| (BytesRead != sizeof(HANDLE))) {
@@ -493,7 +499,6 @@ static int send_handles_to_child(apr_pool_t *p,
void get_listeners_from_parent(server_rec *s)
{
WSAPROTOCOL_INFO WSAProtocolInfo;
- HANDLE pipe;
ap_listen_rec *lr;
DWORD BytesRead;
int lcnt = 0;
@@ -510,9 +515,10 @@ void get_listeners_from_parent(server_rec *s)
/* Open the pipe to the parent process to receive the inherited socket
* data. The sockets have been set to listening in the parent process.
+ *
+ * *** We now do this was back in winnt_rewrite_args
+ * pipe = GetStdHandle(STD_INPUT_HANDLE);
*/
- pipe = GetStdHandle(STD_INPUT_HANDLE);
-
for (lr = ap_listeners; lr; lr = lr->next, ++lcnt) {
if (!ReadFile(pipe, &WSAProtocolInfo, sizeof(WSAPROTOCOL_INFO),
&BytesRead, (LPOVERLAPPED) NULL)) {
@@ -618,8 +624,6 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
apr_status_t rv;
apr_pool_t *ptemp;
apr_procattr_t *attr;
- apr_file_t *child_out;
- apr_file_t *child_err;
apr_proc_t new_child;
HANDLE hExitEvent;
HANDLE waitlist[2]; /* see waitlist_e */
@@ -674,36 +678,6 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
return -1;
}
- /* Open a null handle to soak info from the child */
- if (((rv = apr_file_open(&child_out, "NUL", APR_READ | APR_WRITE,
- APR_OS_DEFAULT, ptemp)) != APR_SUCCESS)
- || ((rv = apr_procattr_child_out_set(attr, child_out, NULL))
- != APR_SUCCESS)) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
- "Parent: Unable to connect child stdout to NUL.");
- apr_pool_destroy(ptemp);
- return -1;
- }
-
- /* Connect the child's initial stderr to our main server error log
- * or share our own stderr handle.
- */
- if (ap_server_conf->error_log) {
- child_err = ap_server_conf->error_log;
- }
- else {
- rv = apr_file_open_stderr(&child_err, ptemp);
- }
- if (rv == APR_SUCCESS) {
- if ((rv = apr_procattr_child_err_set(attr, child_err, NULL))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf,
- "Parent: Unable to connect child stderr.");
- apr_pool_destroy(ptemp);
- return -1;
- }
- }
-
/* Create the child_ready_event */
waitlist[waitlist_ready] = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!waitlist[waitlist_ready]) {
@@ -802,6 +776,8 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
return -1;
}
+ apr_file_close(new_child.in);
+
*child_exit_event = hExitEvent;
*child_proc = new_child.hproc;
*child_pid = new_child.pid;
@@ -1105,6 +1081,9 @@ void winnt_rewrite_args(process_rec *process)
pid = getenv("AP_PARENT_PID");
if (pid)
{
+ HANDLE filehand, newhand;
+ HANDLE hproc = GetCurrentProcess();
+
/* This is the child */
my_pid = GetCurrentProcessId();
parent_pid = (DWORD) atol(pid);
@@ -1112,6 +1091,36 @@ void winnt_rewrite_args(process_rec *process)
/* Prevent holding open the (nonexistant) console */
ap_real_exit_code = 0;
+ /* The parent gave us stdin, we need to remember this
+ * handle, and no longer inherit it at our children
+ * (we can't slurp it up now, we just aren't ready yet).
+ */
+ pipe = GetStdHandle(STD_INPUT_HANDLE);
+
+ if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+ /* This doesn't work for 9x, but it's cleaner. */
+ SetHandleInformation(pipe, HANDLE_FLAG_INHERIT, 0);
+ }
+ else if (DuplicateHandle(hproc, pipe,
+ hproc, &filehand, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ CloseHandle(pipe);
+ pipe = filehand;
+ }
+
+ /* The parent gave us stdout of the NUL device,
+ * and expects us to suck up stdin of all of our
+ * shared handles and data from the parent.
+ * Don't infect child processes with our stdin
+ * handle, use another handle to NUL!
+ */
+ if ((filehand = GetStdHandle(STD_OUTPUT_HANDLE))
+ && DuplicateHandle(hproc, filehand,
+ hproc, &newhand, 0,
+ TRUE, DUPLICATE_SAME_ACCESS)) {
+ SetStdHandle(STD_INPUT_HANDLE, newhand);
+ }
+
/* The parent is responsible for providing the
* COMPLETE ARGUMENTS REQUIRED to the child.
*
@@ -1258,6 +1267,8 @@ void winnt_rewrite_args(process_rec *process)
*/
if (osver.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
+ apr_file_t *nullfile;
+
if (!errout) {
mpm_nt_eventlog_stderr_open(service_name, process->pool);
}
@@ -1266,6 +1277,30 @@ void winnt_rewrite_args(process_rec *process)
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) {
+ HANDLE hproc = GetCurrentProcess();
+ HANDLE nullstdout = NULL;
+ HANDLE nullhandle;
+
+ /* Duplicate the handle to be inherited by children */
+ if ((apr_os_file_get(&nullhandle, nullfile) == APR_SUCCESS)
+ && DuplicateHandle(hproc, nullhandle,
+ hproc, &nullstdout,
+ 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ SetStdHandle(STD_OUTPUT_HANDLE, nullstdout);
+ }
+
+ /* Close the original handle, we used the duplicate */
+ apr_file_close(nullfile);
+ }
}
}
@@ -1604,6 +1639,9 @@ static void winnt_child_init(apr_pool_t *pchild, struct server_rec *s)
/* Set up the listeners */
get_listeners_from_parent(s);
+ /* Done reading from the parent, close that channel */
+ CloseHandle(pipe);
+
ap_my_generation = ap_scoreboard_image->global->running_generation;
}
else {
diff --git a/server/mpm/worker/fdqueue.c b/server/mpm/worker/fdqueue.c
index 6b5485b3..8be7c9fa 100644
--- a/server/mpm/worker/fdqueue.c
+++ b/server/mpm/worker/fdqueue.c
@@ -58,8 +58,7 @@ apr_status_t ap_queue_info_create(fd_queue_info_t **queue_info,
apr_status_t rv;
fd_queue_info_t *qi;
- qi = apr_palloc(pool, sizeof(*qi));
- memset(qi, 0, sizeof(*qi));
+ qi = apr_pcalloc(pool, sizeof(*qi));
rv = apr_thread_mutex_create(&qi->idlers_mutex, APR_THREAD_MUTEX_DEFAULT,
pool);
diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c
index a9d822f5..b6b9447b 100644
--- a/server/mpm/worker/worker.c
+++ b/server/mpm/worker/worker.c
@@ -1813,12 +1813,10 @@ int ap_mpm_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
active_children = 0;
for (index = 0; index < ap_daemons_limit; ++index) {
- if (MPM_CHILD_PID(index) != 0) {
- if (kill(MPM_CHILD_PID(index), 0) == 0) {
- active_children = 1;
- /* Having just one child is enough to stay around */
- break;
- }
+ if (ap_mpm_safe_kill(MPM_CHILD_PID(index), 0) == APR_SUCCESS) {
+ active_children = 1;
+ /* Having just one child is enough to stay around */
+ break;
}
}
} while (!shutdown_pending && active_children &&
diff --git a/server/mpm_common.c b/server/mpm_common.c
index 26a74891..f8063733 100644
--- a/server/mpm_common.c
+++ b/server/mpm_common.c
@@ -126,6 +126,11 @@ static int reclaim_one_pid(pid_t pid, action_t action)
apr_proc_t proc;
apr_status_t waitret;
+ /* Ensure pid sanity. */
+ if (pid < 1) {
+ return 1;
+ }
+
proc.pid = pid;
waitret = apr_proc_wait(&proc, NULL, NULL, APR_NOWAIT);
if (waitret != APR_CHILD_NOTDONE) {
@@ -305,6 +310,66 @@ void ap_relieve_child_processes(void)
cur_extra = next;
}
}
+
+/* Before sending the signal to the pid this function verifies that
+ * the pid is a member of the current process group; either using
+ * apr_proc_wait(), where waitpid() guarantees to fail for non-child
+ * processes; or by using getpgid() directly, if available. */
+apr_status_t ap_mpm_safe_kill(pid_t pid, int sig)
+{
+#ifndef HAVE_GETPGID
+ apr_proc_t proc;
+ apr_status_t rv;
+ apr_exit_why_e why;
+ int status;
+
+ /* Ensure pid sanity */
+ if (pid < 1) {
+ return APR_EINVAL;
+ }
+
+ proc.pid = pid;
+ rv = apr_proc_wait(&proc, &status, &why, APR_NOWAIT);
+ if (rv == APR_CHILD_DONE) {
+#ifdef AP_MPM_WANT_PROCESS_CHILD_STATUS
+ /* The child already died - log the termination status if
+ * necessary: */
+ ap_process_child_status(&proc, why, status);
+#endif
+ return APR_EINVAL;
+ }
+ else if (rv != APR_CHILD_NOTDONE) {
+ /* The child is already dead and reaped, or was a bogus pid -
+ * log this either way. */
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf,
+ "cannot send signal %d to pid %ld (non-child or "
+ "already dead)", sig, (long)pid);
+ return APR_EINVAL;
+ }
+#else
+ pid_t pg;
+
+ /* Ensure pid sanity. */
+ if (pid < 1) {
+ return APR_EINVAL;
+ }
+
+ pg = getpgid(pid);
+ if (pg == -1) {
+ /* Process already dead... */
+ return errno;
+ }
+
+ if (pg != getpgrp()) {
+ ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf,
+ "refusing to send signal %d to pid %ld outside "
+ "process group", sig, (long)pid);
+ return APR_EINVAL;
+ }
+#endif
+
+ return kill(pid, sig) ? errno : APR_SUCCESS;
+}
#endif /* AP_MPM_WANT_RECLAIM_CHILD_PROCESSES */
#ifdef AP_MPM_WANT_WAIT_OR_TIMEOUT
@@ -1217,6 +1282,10 @@ apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf)
if (sigaction(SIGILL, &sa, NULL) < 0)
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGILL)");
#endif
+#ifdef SIGFPE
+ if (sigaction(SIGFPE, &sa, NULL) < 0)
+ ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, "sigaction(SIGFPE)");
+#endif
#else /* NO_USE_SIGACTION */
@@ -1233,6 +1302,9 @@ apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf)
#ifdef SIGILL
apr_signal(SIGILL, sig_coredump);
#endif /* SIGILL */
+#ifdef SIGFPE
+ apr_signal(SIGFPE, sig_coredump);
+#endif /* SIGFPE */
#endif /* NO_USE_SIGACTION */
diff --git a/server/request.c b/server/request.c
index 1aff7304..92e91547 100644
--- a/server/request.c
+++ b/server/request.c
@@ -615,6 +615,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
opts.add = this_dir->opts_add;
opts.remove = this_dir->opts_remove;
opts.override = this_dir->override;
+ opts.override_opts = this_dir->override_opts;
/* Set aside path_info to merge back onto path_info later.
* If r->filename is a directory, we must remerge the path_info,
@@ -1741,9 +1742,9 @@ AP_DECLARE(request_rec *) ap_sub_req_lookup_dirent(const apr_finfo_t *dirent,
/* ap_make_full_path overallocated the buffers
* by one character to help us out here.
*/
- strcpy(rnew->filename + strlen(rnew->filename), "/");
+ strcat(rnew->filename, "/");
if (!rnew->path_info || !*rnew->path_info) {
- strcpy(rnew->uri + strlen(rnew->uri ), "/");
+ strcat(rnew->uri, "/");
}
}
diff --git a/server/util.c b/server/util.c
index 55ed076b..e1be3d18 100644
--- a/server/util.c
+++ b/server/util.c
@@ -2074,10 +2074,9 @@ AP_DECLARE(void) ap_content_type_tolower(char *str)
if (semi) {
*semi = '\0';
}
- while (*str) {
- *str = apr_tolower(*str);
- ++str;
- }
+
+ ap_str_tolower(str);
+
if (semi) {
*semi = ';';
}