Skip to content

Commit 5439276

Browse files
committed
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
1 parent 416e64f commit 5439276

2 files changed

Lines changed: 52 additions & 3 deletions

File tree

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ Changes with Apache 2.1.0-dev
22

33
[Remove entries to the current 2.0 section below, when backported]
44

5+
*) mod_log_config: Fix corruption of buffered logs with threaded
6+
MPMs. PR 25520. [Jeff Trawick]
7+
58
*) Build array of allowed methods with proper dimensions, fixing
69
possible memory corruption. [Jeff Trawick]
710

modules/loggers/mod_log_config.c

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
#include "apr_lib.h"
188188
#include "apr_hash.h"
189189
#include "apr_optional.h"
190+
#include "apr_anylock.h"
190191

191192
#define APR_WANT_STRFUNC
192193
#include "apr_want.h"
@@ -199,6 +200,7 @@
199200
#include "http_log.h"
200201
#include "http_protocol.h"
201202
#include "util_time.h"
203+
#include "ap_mpm.h"
202204

203205
#if APR_HAVE_UNISTD_H
204206
#include <unistd.h>
@@ -237,6 +239,7 @@ static ap_log_writer* ap_log_set_writer(ap_log_writer *handle);
237239
static ap_log_writer *log_writer = ap_default_log_writer;
238240
static ap_log_writer_init *log_writer_init = ap_default_log_writer_init;
239241
static int buffered_logs = 0; /* default unbuffered */
242+
static apr_array_header_t *all_buffered_logs = NULL;
240243

241244
/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
242245
* guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
@@ -290,6 +293,7 @@ typedef struct {
290293
apr_file_t *handle;
291294
apr_size_t outcnt;
292295
char outbuf[LOG_BUFSIZE];
296+
apr_anylock_t mutex;
293297
} buffered_log;
294298

295299
typedef struct {
@@ -1215,6 +1219,10 @@ static apr_status_t flush_all_logs(void *data)
12151219

12161220
static int init_config_log(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s)
12171221
{
1222+
if (buffered_logs) {
1223+
all_buffered_logs = apr_array_make(p, 5, sizeof(buffered_log *));
1224+
}
1225+
12181226
/* First, do "physical" server, which gets default log fd and format
12191227
* for the virtual servers, if they don't override...
12201228
*/
@@ -1231,9 +1239,41 @@ static int init_config_log(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server
12311239

12321240
static void init_child(apr_pool_t *p, server_rec *s)
12331241
{
1242+
int mpm_threads;
1243+
1244+
ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
1245+
12341246
/* Now register the last buffer flush with the cleanup engine */
12351247
if (buffered_logs) {
1248+
int i;
1249+
buffered_log **array = (buffered_log **)all_buffered_logs->elts;
1250+
12361251
apr_pool_cleanup_register(p, s, flush_all_logs, flush_all_logs);
1252+
1253+
for (i = 0; i < all_buffered_logs->nelts; i++) {
1254+
buffered_log *this = array[i];
1255+
1256+
#if APR_HAS_THREADS
1257+
if (mpm_threads > 1) {
1258+
apr_status_t rv;
1259+
1260+
this->mutex.type = apr_anylock_threadmutex;
1261+
rv = apr_thread_mutex_create(&this->mutex.lock.tm,
1262+
APR_THREAD_MUTEX_DEFAULT,
1263+
p);
1264+
if (rv != APR_SUCCESS) {
1265+
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
1266+
"could not initialize buffered log mutex, "
1267+
"transfer log may become corrupted");
1268+
this->mutex.type = apr_anylock_none;
1269+
}
1270+
}
1271+
else
1272+
#endif
1273+
{
1274+
this->mutex.type = apr_anylock_none;
1275+
}
1276+
}
12371277
}
12381278
}
12391279

@@ -1321,12 +1361,13 @@ static void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s,
13211361
const char* name)
13221362
{
13231363
buffered_log *b;
1324-
b = apr_palloc(p, sizeof(buffered_log));
1364+
b = apr_pcalloc(p, sizeof(buffered_log));
13251365
b->handle = ap_default_log_writer_init(p, s, name);
1326-
b->outcnt = 0;
13271366

1328-
if (b->handle)
1367+
if (b->handle) {
1368+
*(buffered_log **)apr_array_push(all_buffered_logs) = b;
13291369
return b;
1370+
}
13301371
else
13311372
return NULL;
13321373
}
@@ -1344,6 +1385,9 @@ static apr_status_t ap_buffered_log_writer(request_rec *r,
13441385
apr_status_t rv;
13451386
buffered_log *buf = (buffered_log*)handle;
13461387

1388+
if ((rv = APR_ANYLOCK_LOCK(&buf->mutex)) != APR_SUCCESS) {
1389+
return rv;
1390+
}
13471391

13481392
if (len + buf->outcnt > LOG_BUFSIZE) {
13491393
flush_log(buf);
@@ -1368,6 +1412,8 @@ static apr_status_t ap_buffered_log_writer(request_rec *r,
13681412
buf->outcnt += len;
13691413
rv = APR_SUCCESS;
13701414
}
1415+
1416+
APR_ANYLOCK_UNLOCK(&buf->mutex);
13711417
return rv;
13721418
}
13731419

0 commit comments

Comments
 (0)