From: Jeff Trawick Date: Wed, 3 Mar 2004 11:07:50 +0000 (+0000) Subject: merge this fix from 2.1-dev: X-Git-Tag: 2.0.49~54 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=01bd3f5afd74514153aae76c88150bbcdee53dd7;p=thirdparty%2Fapache%2Fhttpd.git merge this fix from 2.1-dev: mod_log_config: Fix corruption of buffered logs with threaded MPMs. PR 25520. PR: 25520 Reviewed by: stoddard, jerenkrantz git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/APACHE_2_0_BRANCH@102845 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 3345660c936..fab16baba8c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ Changes with Apache 2.0.49 + *) mod_log_config: Fix corruption of buffered logs with threaded + MPMs. PR 25520. [Jeff Trawick] + *) Fix mod_include's expression parser to recognize strings correctly even if they start with an escaped token. [André Malo] diff --git a/STATUS b/STATUS index 155244ff48a..ae184c37edf 100644 --- a/STATUS +++ b/STATUS @@ -1,5 +1,5 @@ APACHE 2.0 STATUS: -*-text-*- -Last modified at [$Date: 2004/03/03 10:51:49 $] +Last modified at [$Date: 2004/03/03 11:07:48 $] Release: @@ -249,19 +249,6 @@ PATCHES TO BACKPORT FROM 2.1 nd replies: But if it can't be 0 the alternatives thereafter make no sense anymore, right? - * Fix corruption of buffered logs with threaded MPMs. PR 25520. - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/loggers/mod_log_config.c?r1=1.108&r2=1.109 - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/loggers/mod_log_config.c?r1=1.109&r2=1.110 - [gosh nd, must have lost the commit message for that second one; - I need to stop using silly gcc 3.2 I think] - oops, 2 additional fixes needed: - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/loggers/mod_log_config.c?r1=1.113&r2=1.114 - [maybe nd didn't do such a big favor after all ;) ] - Fix existing bug that leads to segfault with this fix if - "BufferedLogs Off" is used: - http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/loggers/mod_log_config.c?r1=1.114&r2=1.115 - +1: trawick, stoddard, jerenkrantz - * mod_isapi: GetServerVariable("ALL_RAW") returned the wrong buffer size. PR 20617 [Jesse Pelton ] http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/arch/win32/mod_isapi.c?r1=1.96&r2=1.97 diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c index 90520d4eab8..3c9fe413e4a 100644 --- a/modules/loggers/mod_log_config.c +++ b/modules/loggers/mod_log_config.c @@ -144,6 +144,7 @@ #include "apr_lib.h" #include "apr_hash.h" #include "apr_optional.h" +#include "apr_anylock.h" #define APR_WANT_STRFUNC #include "apr_want.h" @@ -156,6 +157,7 @@ #include "http_log.h" #include "http_protocol.h" #include "util_time.h" +#include "ap_mpm.h" #if APR_HAVE_UNISTD_H #include @@ -194,6 +196,7 @@ static void ap_log_set_writer(ap_log_writer *handle); static ap_log_writer *log_writer = ap_default_log_writer; static ap_log_writer_init *log_writer_init = ap_default_log_writer_init; static int buffered_logs = 0; /* default unbuffered */ +static apr_array_header_t *all_buffered_logs = NULL; /* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512 @@ -247,6 +250,7 @@ typedef struct { apr_file_t *handle; apr_size_t outcnt; char outbuf[LOG_BUFSIZE]; + apr_anylock_t mutex; } buffered_log; typedef struct { @@ -1037,8 +1041,10 @@ static const char *set_cookie_log(cmd_parms *cmd, void *dummy, const char *fn) static const char *set_buffered_logs_on(cmd_parms *parms, void *dummy, int flag) { buffered_logs = flag; - ap_log_set_writer_init(ap_buffered_log_writer_init); - ap_log_set_writer(ap_buffered_log_writer); + if (buffered_logs) { + ap_log_set_writer_init(ap_buffered_log_writer_init); + ap_log_set_writer(ap_buffered_log_writer); + } return NULL; } static const command_rec config_log_cmds[] = @@ -1172,10 +1178,17 @@ static apr_status_t flush_all_logs(void *data) static int init_config_log(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s) { - /* First, do "physical" server, which gets default log fd and format + int res; + + /* First init the buffered logs array, which is needed when opening the logs. */ + if (buffered_logs) { + all_buffered_logs = apr_array_make(p, 5, sizeof(buffered_log *)); + } + + /* Next, do "physical" server, which gets default log fd and format * for the virtual servers, if they don't override... */ - int res = open_multi_logs(s, p); + res = open_multi_logs(s, p); /* Then, virtual servers */ @@ -1188,9 +1201,41 @@ static int init_config_log(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server static void init_child(apr_pool_t *p, server_rec *s) { + int mpm_threads; + + ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads); + /* Now register the last buffer flush with the cleanup engine */ if (buffered_logs) { + int i; + buffered_log **array = (buffered_log **)all_buffered_logs->elts; + apr_pool_cleanup_register(p, s, flush_all_logs, flush_all_logs); + + for (i = 0; i < all_buffered_logs->nelts; i++) { + buffered_log *this = array[i]; + +#if APR_HAS_THREADS + if (mpm_threads > 1) { + apr_status_t rv; + + this->mutex.type = apr_anylock_threadmutex; + rv = apr_thread_mutex_create(&this->mutex.lock.tm, + APR_THREAD_MUTEX_DEFAULT, + p); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, + "could not initialize buffered log mutex, " + "transfer log may become corrupted"); + this->mutex.type = apr_anylock_none; + } + } + else +#endif + { + this->mutex.type = apr_anylock_none; + } + } } } @@ -1272,12 +1317,13 @@ static void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s, const char* name) { buffered_log *b; - b = apr_palloc(p, sizeof(buffered_log)); + b = apr_pcalloc(p, sizeof(buffered_log)); b->handle = ap_default_log_writer_init(p, s, name); - b->outcnt = 0; - if (b->handle) + if (b->handle) { + *(buffered_log **)apr_array_push(all_buffered_logs) = b; return b; + } else return NULL; } @@ -1295,6 +1341,9 @@ static apr_status_t ap_buffered_log_writer(request_rec *r, apr_status_t rv; buffered_log *buf = (buffered_log*)handle; + if ((rv = APR_ANYLOCK_LOCK(&buf->mutex)) != APR_SUCCESS) { + return rv; + } if (len + buf->outcnt > LOG_BUFSIZE) { flush_log(buf); @@ -1319,6 +1368,8 @@ static apr_status_t ap_buffered_log_writer(request_rec *r, buf->outcnt += len; rv = APR_SUCCESS; } + + APR_ANYLOCK_UNLOCK(&buf->mutex); return rv; }