summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/core.c6
-rw-r--r--server/gen_test_char.c4
-rw-r--r--server/listen.c46
-rw-r--r--server/mpm/experimental/event/fdqueue.c10
-rw-r--r--server/mpm/prefork/prefork.c12
-rw-r--r--server/mpm/winnt/mpm_winnt.c62
-rw-r--r--server/mpm/worker/fdqueue.c18
-rw-r--r--server/request.c10
-rw-r--r--server/scoreboard.c12
9 files changed, 102 insertions, 78 deletions
diff --git a/server/core.c b/server/core.c
index 0e479b0c..3b1b01b7 100644
--- a/server/core.c
+++ b/server/core.c
@@ -1356,8 +1356,8 @@ static const char *set_override(cmd_parms *cmd, void *d_, const char *l)
/* Throw a warning if we're in <Location> or <Files> */
if (ap_check_cmd_context(cmd, NOT_IN_LOCATION | NOT_IN_FILES)) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server,
- "Useless use of AllowOverride in line %d.",
- cmd->directive->line_num);
+ "Useless use of AllowOverride in line %d of %s.",
+ cmd->directive->line_num, cmd->directive->filename);
}
d->override = OR_NONE;
@@ -1458,7 +1458,7 @@ static const char *set_options(cmd_parms *cmd, void *d_, const char *l)
return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL);
}
- if (!(cmd->override_opts & opt) && opt != OPT_NONE) {
+ if ( (cmd->override_opts & opt) != opt ) {
return apr_pstrcat(cmd->pool, "Option ", w, " not allowed here", NULL);
}
else if (action == '-') {
diff --git a/server/gen_test_char.c b/server/gen_test_char.c
index 587583ae..59947d58 100644
--- a/server/gen_test_char.c
+++ b/server/gen_test_char.c
@@ -90,8 +90,8 @@ int main(int argc, char *argv[])
flags |= T_OS_ESCAPE_PATH;
}
- /* these are the "tspecials" from RFC2068 */
- if (c && (apr_iscntrl(c) || strchr(" \t()<>@,;:\\/[]?={}", c))) {
+ /* these are the "tspecials" (RFC2068) or "separators" (RFC2616) */
+ if (c && (apr_iscntrl(c) || strchr(" \t()<>@,;:\\\"/[]?={}", c))) {
flags |= T_HTTP_TOKEN_STOP;
}
diff --git a/server/listen.c b/server/listen.c
index f679f058..d1e6da8e 100644
--- a/server/listen.c
+++ b/server/listen.c
@@ -377,14 +377,22 @@ static int open_listeners(apr_pool_t *pool)
}
else {
#if APR_HAVE_IPV6
+ ap_listen_rec *cur;
int v6only_setting;
+ int skip = 0;
/* If we have the unspecified IPv4 address (0.0.0.0) and
* the unspecified IPv6 address (::) is next, we need to
* swap the order of these in the list. We always try to
* bind to IPv6 first, then IPv4, since an IPv6 socket
* might be able to receive IPv4 packets if V6ONLY is not
- * enabled, but never the other way around. */
+ * enabled, but never the other way around.
+ * Note: In some configurations, the unspecified IPv6 address
+ * could be even later in the list. This logic only corrects
+ * the situation where it is next in the list, such as when
+ * apr_sockaddr_info_get() returns an IPv4 and an IPv6 address,
+ * in that order.
+ */
if (lr->next != NULL
&& IS_INADDR_ANY(lr->bind_addr)
&& lr->bind_addr->port == lr->next->bind_addr->port
@@ -402,26 +410,32 @@ static int open_listeners(apr_pool_t *pool)
lr = next;
}
- /* If we are trying to bind to 0.0.0.0 and the previous listener
+ /* If we are trying to bind to 0.0.0.0 and a previous listener
* was :: on the same port and in turn that socket does not have
* the IPV6_V6ONLY flag set; we must skip the current attempt to
* listen (which would generate an error). IPv4 will be handled
* on the established IPv6 socket.
*/
- if (previous != NULL
- && IS_INADDR_ANY(lr->bind_addr)
- && lr->bind_addr->port == previous->bind_addr->port
- && IS_IN6ADDR_ANY(previous->bind_addr)
- && apr_socket_opt_get(previous->sd, APR_IPV6_V6ONLY,
- &v6only_setting) == APR_SUCCESS
- && v6only_setting == 0) {
-
- /* Remove the current listener from the list */
- previous->next = lr->next;
- lr = previous; /* maintain current value of previous after
- * post-loop expression is evaluated
- */
- continue;
+ if (IS_INADDR_ANY(lr->bind_addr)) {
+ for (cur = ap_listeners; cur != lr; cur = cur->next) {
+ if (lr->bind_addr->port == cur->bind_addr->port
+ && IS_IN6ADDR_ANY(cur->bind_addr)
+ && apr_socket_opt_get(cur->sd, APR_IPV6_V6ONLY,
+ &v6only_setting) == APR_SUCCESS
+ && v6only_setting == 0) {
+
+ /* Remove the current listener from the list */
+ previous->next = lr->next;
+ lr = previous; /* maintain current value of previous after
+ * post-loop expression is evaluated
+ */
+ skip = 1;
+ break;
+ }
+ }
+ if (skip) {
+ continue;
+ }
}
#endif
if (make_sock(pool, lr) == APR_SUCCESS) {
diff --git a/server/mpm/experimental/event/fdqueue.c b/server/mpm/experimental/event/fdqueue.c
index c0ef9bbb..5a1baa94 100644
--- a/server/mpm/experimental/event/fdqueue.c
+++ b/server/mpm/experimental/event/fdqueue.c
@@ -194,10 +194,16 @@ void ap_push_pool(fd_queue_info_t * queue_info,
(*new_recycle));
new_recycle->pool = pool_to_recycle;
for (;;) {
- new_recycle->next = queue_info->recycled_pools;
+ /*
+ * Save queue_info->recycled_pool in local variable next because
+ * new_recycle->next can be changed after apr_atomic_casptr
+ * function call. For gory details see PR 44402.
+ */
+ struct recycled_pool *next = queue_info->recycled_pools;
+ new_recycle->next = next;
if (apr_atomic_casptr
((volatile void **) &(queue_info->recycled_pools),
- new_recycle, new_recycle->next) == new_recycle->next) {
+ new_recycle, next) == next) {
break;
}
}
diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c
index d3c93a63..3849c222 100644
--- a/server/mpm/prefork/prefork.c
+++ b/server/mpm/prefork/prefork.c
@@ -536,7 +536,10 @@ static void child_main(int child_num_arg)
bucket_alloc = apr_bucket_alloc_create(pchild);
- while (!die_now) {
+ /* die_now is set when AP_SIG_GRACEFUL is received in the child;
+ * shutdown_pending is set when SIGTERM is received when running
+ * in single process mode. */
+ while (!die_now && !shutdown_pending) {
conn_rec *current_conn;
void *csd;
@@ -577,6 +580,12 @@ static void child_main(int child_num_arg)
if (one_process && shutdown_pending) {
return;
}
+ else if (die_now) {
+ /* In graceful stop/restart; drop the mutex
+ * and terminate the child. */
+ SAFE_ACCEPT(accept_mutex_off());
+ clean_child_exit(0);
+ }
continue;
}
/* Single Unix documents select as returning errnos
@@ -587,6 +596,7 @@ static void child_main(int child_num_arg)
*/
ap_log_error(APLOG_MARK, APLOG_ERR, status,
ap_server_conf, "apr_pollset_poll: (listen)");
+ SAFE_ACCEPT(accept_mutex_off());
clean_child_exit(1);
}
diff --git a/server/mpm/winnt/mpm_winnt.c b/server/mpm/winnt/mpm_winnt.c
index 120adfc0..52c4ff9c 100644
--- a/server/mpm/winnt/mpm_winnt.c
+++ b/server/mpm/winnt/mpm_winnt.c
@@ -618,7 +618,6 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
/* 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;
@@ -630,11 +629,13 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
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);
@@ -680,7 +681,8 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
}
/* httpd-2.0/2.2 specific to work around apr_proc_create bugs */
- if (((rv = apr_file_open_stdout(&child_out, p))
+ /* set "NUL" as sysout for the child */
+ if (((rv = apr_file_open(&child_out, "NUL", APR_WRITE | APR_READ, APR_OS_DEFAULT,p))
!= APR_SUCCESS) ||
((rv = apr_procattr_child_out_set(attr, child_out, NULL))
!= APR_SUCCESS)) {
@@ -714,21 +716,15 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
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) {
@@ -740,7 +736,7 @@ static int create_process(apr_pool_t *p, HANDLE *child_proc, HANDLE *child_exit_
CloseHandle(new_child.hproc);
return -1;
}
-
+ apr_file_close(child_out);
ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS, ap_server_conf,
"Parent: Created child process %d", new_child.pid);
@@ -1435,26 +1431,6 @@ 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) {
@@ -1594,10 +1570,6 @@ static int winnt_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pt
}
}
}
- 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
@@ -1613,6 +1585,12 @@ static int winnt_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *pt
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 */
{
diff --git a/server/mpm/worker/fdqueue.c b/server/mpm/worker/fdqueue.c
index 8be7c9fa..d46dd536 100644
--- a/server/mpm/worker/fdqueue.c
+++ b/server/mpm/worker/fdqueue.c
@@ -94,10 +94,14 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_t *queue_info,
sizeof(*new_recycle));
new_recycle->pool = pool_to_recycle;
for (;;) {
- new_recycle->next = queue_info->recycled_pools;
+ /* Save queue_info->recycled_pool in local variable next because
+ * new_recycle->next can be changed after apr_atomic_casptr
+ * function call. For gory details see PR 44402.
+ */
+ struct recycled_pool *next = queue_info->recycled_pools;
+ new_recycle->next = next;
if (apr_atomic_casptr((volatile void**)&(queue_info->recycled_pools),
- new_recycle, new_recycle->next) ==
- new_recycle->next) {
+ new_recycle, next) == next) {
break;
}
}
@@ -184,6 +188,14 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue_info_t *queue_info,
apr_atomic_dec32(&(queue_info->idlers));
/* Atomically pop a pool from the recycled list */
+
+ /* This function is safe only as long as it is single threaded because
+ * it reaches into the queue and accesses "next" which can change.
+ * We are OK today because it is only called from the listener thread.
+ * cas-based pushes do not have the same limitation - any number can
+ * happen concurrently with a single cas-based pop.
+ */
+
for (;;) {
struct recycled_pool *first_pool = queue_info->recycled_pools;
if (first_pool == NULL) {
diff --git a/server/request.c b/server/request.c
index 92e91547..fe4026a3 100644
--- a/server/request.c
+++ b/server/request.c
@@ -152,14 +152,10 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
return access_status;
}
- /* Excluding file-specific requests with no 'true' URI...
+ /* Rerun the location walk, which overrides any map_to_storage config.
*/
- if (!file_req) {
- /* Rerun the location walk, which overrides any map_to_storage config.
- */
- if ((access_status = ap_location_walk(r))) {
- return access_status;
- }
+ if ((access_status = ap_location_walk(r))) {
+ return access_status;
}
/* Only on the main request! */
diff --git a/server/scoreboard.c b/server/scoreboard.c
index 0f657131..060de5ca 100644
--- a/server/scoreboard.c
+++ b/server/scoreboard.c
@@ -118,8 +118,7 @@ void ap_init_scoreboard(void *shared_score)
ap_calc_scoreboard_size();
ap_scoreboard_image =
- calloc(1, sizeof(scoreboard) + server_limit * sizeof(worker_score *) +
- server_limit * lb_limit * sizeof(lb_score *));
+ calloc(1, sizeof(scoreboard) + server_limit * sizeof(worker_score *));
more_storage = shared_score;
ap_scoreboard_image->global = (global_score *)more_storage;
more_storage += sizeof(global_score);
@@ -344,6 +343,9 @@ AP_DECLARE(void) ap_increment_counts(ap_sb_handle_t *sb, request_rec *r)
{
worker_score *ws;
+ if (!sb)
+ return;
+
ws = &ap_scoreboard_image->servers[sb->child_num][sb->thread_num];
#ifdef HAVE_TIMES
@@ -471,6 +473,9 @@ AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num,
AP_DECLARE(int) ap_update_child_status(ap_sb_handle_t *sbh, int status,
request_rec *r)
{
+ if (!sbh)
+ return -1;
+
return ap_update_child_status_from_indexes(sbh->child_num, sbh->thread_num,
status, r);
}
@@ -479,6 +484,9 @@ void ap_time_process_request(ap_sb_handle_t *sbh, int status)
{
worker_score *ws;
+ if (!sbh)
+ return;
+
if (sbh->child_num < 0) {
return;
}