]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
merge this fix from 2.1-dev:
authorJeff Trawick <trawick@apache.org>
Wed, 3 Mar 2004 11:07:50 +0000 (11:07 +0000)
committerJeff Trawick <trawick@apache.org>
Wed, 3 Mar 2004 11:07:50 +0000 (11:07 +0000)
   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

CHANGES
STATUS
modules/loggers/mod_log_config.c

diff --git a/CHANGES b/CHANGES
index 3345660c93652fdce33a8aac31a5c866811e10a5..fab16baba8cd90741455946116c80528a6488a74 100644 (file)
--- 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 155244ff48aef9b8edd1f33b5e642a081499bb69..ae184c37edf69b73c773c2bbd7bb45dff8b14791 100644 (file)
--- 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 <jsp pkc.com>]
         http://cvs.apache.org/viewcvs.cgi/httpd-2.0/modules/arch/win32/mod_isapi.c?r1=1.96&r2=1.97
index 90520d4eab8478a79b16764b9bbe6a4e26a58f9a..3c9fe413e4a120979c3e4d536e0fdd88fc8ebf47 100644 (file)
 #include "apr_lib.h"
 #include "apr_hash.h"
 #include "apr_optional.h"
+#include "apr_anylock.h"
 
 #define APR_WANT_STRFUNC
 #include "apr_want.h"
 #include "http_log.h"
 #include "http_protocol.h"
 #include "util_time.h"
+#include "ap_mpm.h"
 
 #if APR_HAVE_UNISTD_H
 #include <unistd.h>
@@ -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;
 }