summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:17 +0100
committerStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:17 +0100
commit9e615cb6aa4afcee97f8a1646e5a586261a7b81f (patch)
tree0e09fde2404555dc5daf167b38243b5f89c16549 /server
parent1acac7a6b494db24f8f58e44dab7657b6de68742 (diff)
downloadapache2-9e615cb6aa4afcee97f8a1646e5a586261a7b81f.tar.gz
Upstream tarball 2.2.8upstream/2.2.8
Diffstat (limited to 'server')
-rw-r--r--server/core.c15
-rw-r--r--server/log.c38
-rw-r--r--server/mpm/experimental/event/event.c22
-rw-r--r--server/mpm/winnt/child.c93
-rw-r--r--server/mpm/winnt/mpm_winnt.c85
-rw-r--r--server/mpm/winnt/nt_eventlog.c30
-rw-r--r--server/mpm_common.c2
-rw-r--r--server/protocol.c45
-rw-r--r--server/scoreboard.c54
9 files changed, 280 insertions, 104 deletions
diff --git a/server/core.c b/server/core.c
index b4aca33b..0e479b0c 100644
--- a/server/core.c
+++ b/server/core.c
@@ -227,8 +227,7 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
/* Create this conf by duplicating the base, replacing elements
* (or creating copies for merging) where new-> values exist.
*/
- conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
- memcpy(conf, base, sizeof(core_dir_config));
+ conf = (core_dir_config *)apr_pmemdup(a, base, sizeof(core_dir_config));
conf->d = new->d;
conf->d_is_fnmatch = new->d_is_fnmatch;
@@ -286,10 +285,9 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
else if (new->response_code_strings != NULL) {
/* If we merge, the merge-result must have it's own array
*/
- conf->response_code_strings = apr_palloc(a,
+ conf->response_code_strings = apr_pmemdup(a,
+ base->response_code_strings,
sizeof(*conf->response_code_strings) * RESPONSE_CODES);
- memcpy(conf->response_code_strings, base->response_code_strings,
- sizeof(*conf->response_code_strings) * RESPONSE_CODES);
for (i = 0; i < RESPONSE_CODES; ++i) {
if (new->response_code_strings[i] != NULL) {
@@ -497,8 +495,7 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv)
core_server_config *virt = (core_server_config *)virtv;
core_server_config *conf;
- conf = (core_server_config *)apr_palloc(p, sizeof(core_server_config));
- memcpy(conf, virt, sizeof(core_server_config));
+ conf = (core_server_config *)apr_pmemdup(p, virt, sizeof(core_server_config));
if (!conf->access_name) {
conf->access_name = base->access_name;
@@ -1173,6 +1170,9 @@ static const char *set_document_root(cmd_parms *cmd, void *dummy,
/* Make it absolute, relative to ServerRoot */
arg = ap_server_root_relative(cmd->pool, arg);
+ if (arg == NULL) {
+ return "DocumentRoot must be a directory";
+ }
/* TODO: ap_configtestonly && ap_docrootcheck && */
if (apr_filepath_merge((char**)&conf->ap_document_root, NULL, arg,
@@ -3906,6 +3906,7 @@ static conn_rec *core_create_conn(apr_pool_t *ptrans, server_rec *server,
c->id = id;
c->bucket_alloc = alloc;
+ c->clogging_input_filters = 0;
return c;
}
diff --git a/server/log.c b/server/log.c
index 14b4fdc2..3aa20b0b 100644
--- a/server/log.c
+++ b/server/log.c
@@ -161,15 +161,26 @@ static apr_status_t clear_handle_list(void *v)
return APR_SUCCESS;
}
-/* remember to close this handle in the child process */
+/* remember to close this handle in the child process
+ *
+ * On Win32 this makes zero sense, because we don't
+ * take the parent process's child procs.
+ * If the win32 parent instead passed each and every
+ * logger write handle from itself down to the child,
+ * and the parent manages all aspects of keeping the
+ * reliable pipe log children alive, this would still
+ * make no sense :) Cripple it on Win32.
+ */
static void close_handle_in_child(apr_pool_t *p, apr_file_t *f)
{
+#ifndef WIN32
read_handle_t *new_handle;
new_handle = apr_pcalloc(p, sizeof(read_handle_t));
new_handle->next = read_handles;
new_handle->handle = f;
read_handles = new_handle;
+#endif
}
void ap_logs_child_init(apr_pool_t *p, server_rec *s)
@@ -263,7 +274,7 @@ static int log_child(apr_pool_t *p, const char *progname,
apr_status_t rc;
apr_procattr_t *procattr;
apr_proc_t *procnew;
- apr_file_t *errfile;
+ apr_file_t *outfile, *errfile;
if (((rc = apr_procattr_create(&procattr, p)) == APR_SUCCESS)
&& ((rc = apr_procattr_cmdtype_set(procattr,
@@ -282,8 +293,11 @@ static int log_child(apr_pool_t *p, const char *progname,
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)
+ if ((rc = apr_file_open_stdout(&outfile, p)) == APR_SUCCESS) {
+ rc = apr_procattr_child_out_set(procattr, outfile, NULL);
+ if (dummy_stderr)
+ rc = apr_procattr_child_err_set(procattr, outfile, NULL);
+ else if ((rc = apr_file_open_stderr(&errfile, p)) == APR_SUCCESS)
rc = apr_procattr_child_err_set(procattr, errfile, NULL);
}
@@ -421,6 +435,16 @@ int ap_open_logs(apr_pool_t *pconf, apr_pool_t *p /* plog */,
apr_pool_destroy(stderr_pool);
stderr_pool = stderr_p;
replace_stderr = 0;
+ /*
+ * Now that we have dup'ed s_main->error_log to stderr_log
+ * close it and set s_main->error_log to stderr_log. This avoids
+ * this fd being inherited by the next piped logger who would
+ * keep open the writing end of the pipe that this one uses
+ * as stdin. This in turn would prevent the piped logger from
+ * exiting.
+ */
+ apr_file_close(s_main->error_log);
+ s_main->error_log = stderr_log;
}
}
/* note that stderr may still need to be replaced with something
@@ -877,6 +901,12 @@ static apr_status_t piped_log_spawn(piped_log *pl)
else {
char **args;
const char *pname;
+ apr_file_t *outfile, *errfile;
+
+ if ((status = apr_file_open_stdout(&outfile, pl->p)) == APR_SUCCESS)
+ status = apr_procattr_child_out_set(procattr, outfile, NULL);
+ if ((status = apr_file_open_stderr(&errfile, pl->p)) == APR_SUCCESS)
+ status = apr_procattr_child_err_set(procattr, errfile, NULL);
apr_tokenize_to_argv(pl->program, &args, pl->p);
pname = apr_pstrdup(pl->p, args[0]);
diff --git a/server/mpm/experimental/event/event.c b/server/mpm/experimental/event/event.c
index 2a6913b3..261468ea 100644
--- a/server/mpm/experimental/event/event.c
+++ b/server/mpm/experimental/event/event.c
@@ -623,6 +623,15 @@ static int process_socket(apr_pool_t * p, apr_socket_t * sock,
c->sbh = sbh;
}
+ if (c->clogging_input_filters && !c->aborted) {
+ /* Since we have an input filter which 'cloggs' the input stream,
+ * like mod_ssl, lets just do the normal read from input filters,
+ * like the Worker MPM does.
+ */
+ ap_run_process_connection(c);
+ cs->state = CONN_STATE_LINGER;
+ }
+
if (cs->state == CONN_STATE_READ_REQUEST_LINE) {
if (!c->aborted) {
ap_run_process_connection(c);
@@ -639,7 +648,6 @@ static int process_socket(apr_pool_t * p, apr_socket_t * sock,
if (cs->state == CONN_STATE_LINGER) {
ap_lingering_close(c);
- apr_bucket_alloc_destroy(cs->bucket_alloc);
apr_pool_clear(p);
ap_push_pool(worker_queue_info, p);
return 1;
@@ -1020,12 +1028,19 @@ static void *listener_thread(apr_thread_t * thd, void *dummy)
cs = APR_RING_FIRST(&timeout_head);
timeout_time = time_now + TIMEOUT_FUDGE_FACTOR;
while (!APR_RING_EMPTY(&timeout_head, conn_state_t, timeout_list)
- && cs->expiration_time < timeout_time
- && get_worker(&have_idle_worker)) {
+ && cs->expiration_time < timeout_time) {
cs->state = CONN_STATE_LINGER;
APR_RING_REMOVE(cs, timeout_list);
+ apr_thread_mutex_unlock(timeout_mutex);
+
+ if (!get_worker(&have_idle_worker)) {
+ apr_thread_mutex_lock(timeout_mutex);
+ APR_RING_INSERT_HEAD(&timeout_head, cs,
+ conn_state_t, timeout_list);
+ break;
+ }
rc = push2worker(&cs->pfd, event_pollset);
@@ -1038,6 +1053,7 @@ static void *listener_thread(apr_thread_t * thd, void *dummy)
*/
}
have_idle_worker = 0;
+ apr_thread_mutex_lock(timeout_mutex);
cs = APR_RING_FIRST(&timeout_head);
}
apr_thread_mutex_unlock(timeout_mutex);
diff --git a/server/mpm/winnt/child.c b/server/mpm/winnt/child.c
index 8996bfd8..d918e47a 100644
--- a/server/mpm/winnt/child.c
+++ b/server/mpm/winnt/child.c
@@ -80,6 +80,7 @@ void mpm_recycle_completion_context(PCOMP_CONTEXT context)
*/
if (context) {
apr_pool_clear(context->ptrans);
+ context->ba = apr_bucket_alloc_create(context->ptrans);
context->next = NULL;
ResetEvent(context->Overlapped.hEvent);
apr_thread_mutex_lock(qlock);
@@ -175,7 +176,7 @@ PCOMP_CONTEXT mpm_get_completion_context(void)
apr_pool_tag(context->ptrans, "transaction");
context->accept_socket = INVALID_SOCKET;
- context->ba = apr_bucket_alloc_create(pchild);
+ context->ba = apr_bucket_alloc_create(context->ptrans);
apr_atomic_inc32(&num_completion_contexts);
apr_thread_mutex_unlock(child_lock);
@@ -432,12 +433,12 @@ static PCOMP_CONTEXT win9x_get_connection(PCOMP_CONTEXT context)
apr_pool_create_ex(&context->ptrans, pchild, NULL, allocator);
apr_allocator_owner_set(allocator, context->ptrans);
apr_pool_tag(context->ptrans, "transaction");
- context->ba = apr_bucket_alloc_create(pchild);
apr_thread_mutex_unlock(child_lock);
}
while (1) {
apr_pool_clear(context->ptrans);
+ context->ba = apr_bucket_alloc_create(context->ptrans);
context->accept_socket = remove_job();
if (context->accept_socket == INVALID_SOCKET) {
return NULL;
@@ -863,14 +864,15 @@ void child_main(apr_pool_t *pconf)
apr_hash_t *ht;
ap_listen_rec *lr;
HANDLE child_events[2];
- int threads_created = 0;
+ HANDLE *child_handles;
int listener_started = 0;
+ int threads_created = 0;
+ int watch_thread;
+ int time_remains;
+ int cld;
int tid;
- HANDLE *child_handles;
int rv;
- time_t end_time;
int i;
- int cld;
apr_pool_create(&pchild, pconf);
apr_pool_tag(pchild, "pchild");
@@ -1109,21 +1111,71 @@ void child_main(apr_pool_t *pconf)
apr_thread_mutex_unlock(qlock);
}
- /* Give busy worker threads a chance to service their connections */
- ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf,
- "Child %d: Waiting for %d worker threads to exit.", my_pid, threads_created);
- end_time = time(NULL) + 180;
- while (threads_created) {
- rv = wait_for_many_objects(threads_created, child_handles, (DWORD)(end_time - time(NULL)));
- if (rv != WAIT_TIMEOUT) {
- rv = rv - WAIT_OBJECT_0;
- ap_assert((rv >= 0) && (rv < threads_created));
- cleanup_thread(child_handles, &threads_created, rv);
+ /* Give busy threads a chance to service their connections,
+ * (no more than the global server timeout period which
+ * we track in msec remaining).
+ */
+ watch_thread = 0;
+ time_remains = (int)(ap_server_conf->timeout / APR_TIME_C(1000));
+
+ while (threads_created)
+ {
+ int nFailsafe = MAXIMUM_WAIT_OBJECTS;
+ DWORD dwRet;
+
+ /* Every time we roll over to wait on the first group
+ * of MAXIMUM_WAIT_OBJECTS threads, take a breather,
+ * and infrequently update the error log.
+ */
+ if (watch_thread >= threads_created) {
+ if ((time_remains -= 100) < 0)
+ break;
+
+ /* Every 30 seconds give an update */
+ if ((time_remains % 30000) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS,
+ ap_server_conf,
+ "Child %d: Waiting %d more seconds "
+ "for %d worker threads to finish.",
+ my_pid, time_remains / 1000, threads_created);
+ }
+ /* We'll poll from the top, 10 times per second */
+ Sleep(100);
+ watch_thread = 0;
+ }
+
+ /* Fairness, on each iteration we will pick up with the thread
+ * after the one we just removed, even if it's a single thread.
+ * We don't block here.
+ */
+ dwRet = WaitForMultipleObjects(min(threads_created - watch_thread,
+ MAXIMUM_WAIT_OBJECTS),
+ child_handles + watch_thread, 0, 0);
+
+ if (dwRet == WAIT_FAILED) {
+ break;
+ }
+ if (dwRet == WAIT_TIMEOUT) {
+ /* none ready */
+ watch_thread += MAXIMUM_WAIT_OBJECTS;
continue;
}
- break;
+ else if (dwRet >= WAIT_ABANDONED_0) {
+ /* We just got the ownership of the object, which
+ * should happen at most MAXIMUM_WAIT_OBJECTS times.
+ * It does NOT mean that the object is signaled.
+ */
+ if ((nFailsafe--) < 1)
+ break;
+ }
+ else {
+ watch_thread += (dwRet - WAIT_OBJECT_0);
+ if (watch_thread >= threads_created)
+ break;
+ cleanup_thread(child_handles, &threads_created, watch_thread);
+ }
}
-
+
/* Kill remaining threads off the hard way */
if (threads_created) {
ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf,
@@ -1136,7 +1188,10 @@ void child_main(apr_pool_t *pconf)
CloseHandle(child_handles[i]);
/* Reset the scoreboard entry for the thread we just whacked */
score_idx = apr_hash_get(ht, &child_handles[i], sizeof(HANDLE));
- ap_update_child_status_from_indexes(0, *score_idx, SERVER_DEAD, NULL);
+ if (score_idx) {
+ ap_update_child_status_from_indexes(0, *score_idx,
+ SERVER_DEAD, NULL);
+ }
}
ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf,
"Child %d: All worker threads have exited.", my_pid);
diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c
index 4b37d741..120adfc0 100644
--- a/server/mpm/winnt/mpm_winnt.c
+++ b/server/mpm/winnt/mpm_winnt.c
@@ -625,6 +625,7 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
apr_pool_t *ptemp;
apr_procattr_t *attr;
apr_proc_t new_child;
+ apr_file_t *child_out, *child_err;
HANDLE hExitEvent;
HANDLE waitlist[2]; /* see waitlist_e */
char *cmd;
@@ -678,6 +679,22 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
return -1;
}
+ /* httpd-2.0/2.2 specific to work around apr_proc_create bugs */
+ if (((rv = apr_file_open_stdout(&child_out, p))
+ != APR_SUCCESS) ||
+ ((rv = apr_procattr_child_out_set(attr, child_out, NULL))
+ != APR_SUCCESS)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
+ "Parent: Could not set child process stdout");
+ }
+ if (((rv = apr_file_open_stderr(&child_err, p))
+ != APR_SUCCESS) ||
+ ((rv = apr_procattr_child_err_set(attr, child_err, NULL))
+ != APR_SUCCESS)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
+ "Parent: Could not set child process stderr");
+ }
+
/* Create the child_ready_event */
waitlist[waitlist_ready] = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!waitlist[waitlist_ready]) {
@@ -975,9 +992,11 @@ die_now:
event_handles[CHILD_HANDLE] = NULL;
}
}
+ CloseHandle(child_exit_event);
return 0; /* Tell the caller we do not want to restart */
}
winnt_mpm_state = AP_MPMQ_STARTING;
+ CloseHandle(child_exit_event);
return 1; /* Tell the caller we want a restart */
}
@@ -1081,7 +1100,7 @@ void winnt_rewrite_args(process_rec *process)
pid = getenv("AP_PARENT_PID");
if (pid)
{
- HANDLE filehand, newhand;
+ HANDLE filehand;
HANDLE hproc = GetCurrentProcess();
/* This is the child */
@@ -1094,17 +1113,12 @@ void winnt_rewrite_args(process_rec *process)
/* 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).
+ * The original handle is closed below, at apr_file_dup2()
*/
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);
+ if (DuplicateHandle(hproc, pipe,
+ hproc, &filehand, 0, FALSE,
+ DUPLICATE_SAME_ACCESS)) {
pipe = filehand;
}
@@ -1114,13 +1128,17 @@ void winnt_rewrite_args(process_rec *process)
* 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);
+ {
+ apr_file_t *infile, *outfile;
+ if ((apr_file_open_stdout(&outfile, process->pool) == APR_SUCCESS)
+ && (apr_file_open_stdin(&infile, process->pool) == APR_SUCCESS))
+ apr_file_dup2(infile, outfile, process->pool);
}
+ /* This child needs the existing stderr opened for logging,
+ * already
+ */
+
/* The parent is responsible for providing the
* COMPLETE ARGUMENTS REQUIRED to the child.
*
@@ -1286,19 +1304,10 @@ void winnt_rewrite_args(process_rec *process)
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_t *nullstdout;
+ if (apr_file_open_stdout(&nullstdout, process->pool)
+ == APR_SUCCESS)
+ apr_file_dup2(nullstdout, nullfile, process->pool);
apr_file_close(nullfile);
}
}
@@ -1426,6 +1435,26 @@ static int winnt_pre_config(apr_pool_t *pconf_, apr_pool_t *plog, apr_pool_t *pt
service_name);
exit(APEXIT_INIT);
}
+ else if (!one_process && !ap_my_generation) {
+ /* Open a null handle to soak stdout in this process.
+ * We need to emulate apr_proc_detach, unix performs this
+ * same check in the pre_config hook (although it is
+ * arguably premature). Services already fixed this.
+ */
+ apr_file_t *nullfile;
+ apr_status_t rv;
+ apr_pool_t *pproc = apr_pool_parent_get(pconf);
+
+ if ((rv = apr_file_open(&nullfile, "NUL",
+ APR_READ | APR_WRITE, APR_OS_DEFAULT,
+ pproc)) == APR_SUCCESS) {
+ apr_file_t *nullstdout;
+ if (apr_file_open_stdout(&nullstdout, pproc)
+ == APR_SUCCESS)
+ apr_file_dup2(nullstdout, nullfile, pproc);
+ apr_file_close(nullfile);
+ }
+ }
/* Win9x: disable AcceptEx */
if (osver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
diff --git a/server/mpm/winnt/nt_eventlog.c b/server/mpm/winnt/nt_eventlog.c
index a0ae68c9..baa1a88b 100644
--- a/server/mpm/winnt/nt_eventlog.c
+++ b/server/mpm/winnt/nt_eventlog.c
@@ -21,6 +21,7 @@
#include "mpm_winnt.h"
#include "apr_strings.h"
#include "apr_lib.h"
+#include "apr_portable.h"
#include "ap_regkey.h"
static char *display_name = NULL;
@@ -138,7 +139,8 @@ void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
HANDLE hPipeWrite = NULL;
HANDLE hDup = NULL;
DWORD threadid;
- int fd;
+ apr_file_t *eventlog_file;
+ apr_file_t *stderr_file;
display_name = argv0;
@@ -159,27 +161,11 @@ void mpm_nt_eventlog_stderr_open(char *argv0, apr_pool_t *p)
WaitForSingleObject(stderr_ready, INFINITE);
- /* Flush stderr and unset its buffer, then commit and replace stderr.
- * This is typically a noop for Win2K/XP since services with NULL std
- * handles [but valid FILE *'s, oddly enough], but is required
- * for NT 4.0 and to use this code outside of services.
- */
- fflush(stderr);
- setvbuf(stderr, NULL, _IONBF, 0);
- _commit(2 /* stderr */);
- fd = _open_osfhandle((long) hPipeWrite,
- _O_WRONLY | _O_BINARY);
- _dup2(fd, 2);
- _close(fd);
- _setmode(2, _O_BINARY);
-
- /* hPipeWrite was _close()'ed above, and _dup2()'ed
- * to fd 2 creating a new, inherited Win32 handle.
- * Recover that real handle from fd 2.
- */
- hPipeWrite = (HANDLE)_get_osfhandle(2);
-
- SetStdHandle(STD_ERROR_HANDLE, hPipeWrite);
+ if ((apr_file_open_stderr(&stderr_file, p)
+ == APR_SUCCESS)
+ && (apr_os_file_put(&eventlog_file, &hPipeWrite, APR_WRITE, p)
+ == APR_SUCCESS))
+ apr_file_dup2(stderr_file, eventlog_file, p);
/* The code above _will_ corrupt the StdHandle...
* and we must do so anyways. We set this up only
diff --git a/server/mpm_common.c b/server/mpm_common.c
index f8063733..a95b2312 100644
--- a/server/mpm_common.c
+++ b/server/mpm_common.c
@@ -699,7 +699,7 @@ static apr_status_t dummy_connection(ap_pod_t *pod)
* adminstrators can track down the cause of the odd-looking
* requests in their logs.
*/
- srequest = apr_pstrcat(p, "GET / HTTP/1.0\r\nUser-Agent: ",
+ srequest = apr_pstrcat(p, "OPTIONS * HTTP/1.0\r\nUser-Agent: ",
ap_get_server_banner(),
" (internal dummy connection)\r\n\r\n", NULL);
diff --git a/server/protocol.c b/server/protocol.c
index b7145bb7..e5b2e030 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -1399,9 +1399,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(
* can simply insert our buffered data at the front and
* pass the whole bundle down the chain.
*/
- APR_BRIGADE_CONCAT(ctx->bb, bb);
- bb = ctx->bb;
- ctx->bb = NULL;
+ APR_BRIGADE_PREPEND(bb, ctx->bb);
}
return ap_pass_brigade(f->next, bb);
@@ -1539,9 +1537,6 @@ AP_DECLARE(int) ap_vrprintf(request_rec *r, const char *fmt, va_list va)
written = apr_vformatter(r_flush, &vd.vbuff, fmt, va);
- /* tack on null terminator on remaining string */
- *(vd.vbuff.curpos) = '\0';
-
if (written != -1) {
int n = vd.vbuff.curpos - vrprintf_buf;
@@ -1633,6 +1628,44 @@ AP_DECLARE(void) ap_set_last_modified(request_rec *r)
}
}
+typedef struct hdr_ptr {
+ ap_filter_t *f;
+ apr_bucket_brigade *bb;
+} hdr_ptr;
+
+static int send_header(void *data, const char *key, const char *val)
+{
+ ap_fputstrs(((hdr_ptr*)data)->f, ((hdr_ptr*)data)->bb,
+ key, ": ", val, CRLF, NULL);
+ return 1;
+}
+
+AP_DECLARE(void) ap_send_interim_response(request_rec *r, int send_headers)
+{
+ hdr_ptr x;
+
+ if (r->proto_num < 1001) {
+ /* don't send interim response to HTTP/1.0 Client */
+ return;
+ }
+ if (!ap_is_HTTP_INFO(r->status)) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, NULL,
+ "Status is %d - not sending interim response", r->status);
+ return;
+ }
+
+ x.f = r->connection->output_filters;
+ x.bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+ ap_fputstrs(x.f, x.bb, AP_SERVER_PROTOCOL, " ", r->status_line, CRLF, NULL);
+ if (send_headers) {
+ apr_table_do(send_header, &x, r->headers_out, NULL);
+ apr_table_clear(r->headers_out);
+ }
+ ap_fputs(x.f, x.bb, CRLF);
+ ap_fflush(x.f, x.bb);
+ apr_brigade_destroy(x.bb);
+}
+
AP_IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,
(request_rec *r), (r), OK, DECLINED)
AP_IMPLEMENT_HOOK_RUN_ALL(int,log_transaction,
diff --git a/server/scoreboard.c b/server/scoreboard.c
index 9cb7359a..0f657131 100644
--- a/server/scoreboard.c
+++ b/server/scoreboard.c
@@ -40,6 +40,7 @@
AP_DECLARE_DATA scoreboard *ap_scoreboard_image = NULL;
AP_DECLARE_DATA const char *ap_scoreboard_fname = NULL;
AP_DECLARE_DATA int ap_extended_status = 0;
+AP_DECLARE_DATA int ap_mod_status_reqtail = 0;
#if APR_HAS_SHARED_MEMORY
@@ -157,7 +158,7 @@ static apr_status_t create_namebased_scoreboard(apr_pool_t *pool,
rv = apr_shm_create(&ap_scoreboard_shm, scoreboard_size, fname, pool);
if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
- "unable to create scoreboard \"%s\" "
+ "unable to create or access scoreboard \"%s\" "
"(name-based shared memory failure)", fname);
return rv;
}
@@ -204,7 +205,7 @@ static apr_status_t open_scoreboard(apr_pool_t *pconf)
global_pool); /* anonymous shared memory */
if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) {
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
- "Unable to create scoreboard "
+ "Unable to create or access scoreboard "
"(anonymous shared memory failure)");
return rv;
}
@@ -380,6 +381,42 @@ AP_DECLARE(void) ap_create_sb_handle(ap_sb_handle_t **new_sbh, apr_pool_t *p,
(*new_sbh)->thread_num = thread_num;
}
+static void copy_request(char *rbuf, apr_size_t rbuflen, request_rec *r)
+{
+ char *p;
+
+ if (r->the_request == NULL) {
+ apr_cpystrn(rbuf, "NULL", rbuflen);
+ return; /* short circuit below */
+ }
+
+ if (r->parsed_uri.password == NULL) {
+ p = r->the_request;
+ }
+ else {
+ /* Don't reveal the password in the server-status view */
+ p = apr_pstrcat(r->pool, r->method, " ",
+ apr_uri_unparse(r->pool, &r->parsed_uri,
+ APR_URI_UNP_OMITPASSWORD),
+ r->assbackwards ? NULL : " ", r->protocol, NULL);
+ }
+
+ /* now figure out if we copy over the 1st rbuflen chars or the last */
+ if (!ap_mod_status_reqtail) {
+ apr_cpystrn(rbuf, p, rbuflen);
+ }
+ else {
+ apr_size_t slen = strlen(p);
+ if (slen < rbuflen) {
+ /* it all fits anyway */
+ apr_cpystrn(rbuf, p, rbuflen);
+ }
+ else {
+ apr_cpystrn(rbuf, p+(slen-rbuflen+1), rbuflen);
+ }
+ }
+}
+
AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num,
int thread_num,
int status,
@@ -422,18 +459,7 @@ AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num,
conn_rec *c = r->connection;
apr_cpystrn(ws->client, ap_get_remote_host(c, r->per_dir_config,
REMOTE_NOLOOKUP, NULL), sizeof(ws->client));
- if (r->the_request == NULL) {
- apr_cpystrn(ws->request, "NULL", sizeof(ws->request));
- } else if (r->parsed_uri.password == NULL) {
- apr_cpystrn(ws->request, r->the_request, sizeof(ws->request));
- } else {
- /* Don't reveal the password in the server-status view */
- apr_cpystrn(ws->request, apr_pstrcat(r->pool, r->method, " ",
- apr_uri_unparse(r->pool, &r->parsed_uri,
- APR_URI_UNP_OMITPASSWORD),
- r->assbackwards ? NULL : " ", r->protocol, NULL),
- sizeof(ws->request));
- }
+ copy_request(ws->request, sizeof(ws->request), r);
apr_cpystrn(ws->vhost, r->server->server_hostname,
sizeof(ws->vhost));
}