diff options
Diffstat (limited to 'server')
| -rw-r--r-- | server/core.c | 6 | ||||
| -rw-r--r-- | server/gen_test_char.c | 4 | ||||
| -rw-r--r-- | server/listen.c | 46 | ||||
| -rw-r--r-- | server/mpm/experimental/event/fdqueue.c | 10 | ||||
| -rw-r--r-- | server/mpm/prefork/prefork.c | 12 | ||||
| -rw-r--r-- | server/mpm/winnt/mpm_winnt.c | 62 | ||||
| -rw-r--r-- | server/mpm/worker/fdqueue.c | 18 | ||||
| -rw-r--r-- | server/request.c | 10 | ||||
| -rw-r--r-- | server/scoreboard.c | 12 |
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; } |
