From: Jeff Trawick Date: Sat, 17 Jan 2004 00:16:45 +0000 (+0000) Subject: mod_log_config: Fix corruption of buffered logs with threaded X-Git-Tag: pre_ajp_proxy~793 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e6834bc9b4cdd4af90078bc8bf734f9f8e1c09b2;p=apache mod_log_config: Fix corruption of buffered logs with threaded MPMs. PR: 25520 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@102355 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 42b3d3d20f..018e03aa4b 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.1.0-dev [Remove entries to the current 2.0 section below, when backported] + *) mod_log_config: Fix corruption of buffered logs with threaded + MPMs. PR 25520. [Jeff Trawick] + *) Build array of allowed methods with proper dimensions, fixing possible memory corruption. [Jeff Trawick] diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c index 87c9a2f688..7e79a97454 100644 --- a/modules/loggers/mod_log_config.c +++ b/modules/loggers/mod_log_config.c @@ -187,6 +187,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" @@ -199,6 +200,7 @@ #include "http_log.h" #include "http_protocol.h" #include "util_time.h" +#include "ap_mpm.h" #if APR_HAVE_UNISTD_H #include @@ -237,6 +239,7 @@ static ap_log_writer* 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 @@ -290,6 +293,7 @@ typedef struct { apr_file_t *handle; apr_size_t outcnt; char outbuf[LOG_BUFSIZE]; + apr_anylock_t mutex; } buffered_log; typedef struct { @@ -1215,6 +1219,10 @@ 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) { + if (buffered_logs) { + all_buffered_logs = apr_array_make(p, 5, sizeof(buffered_log *)); + } + /* First, do "physical" server, which gets default log fd and format * for the virtual servers, if they don't override... */ @@ -1231,9 +1239,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; + } + } } } @@ -1321,12 +1361,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; } @@ -1344,6 +1385,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); @@ -1368,6 +1412,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; }