httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rpl...@apache.org
Subject svn commit: r451279 - /httpd/httpd/trunk/server/eor_bucket.c
Date Fri, 29 Sep 2006 13:15:09 GMT
Author: rpluem
Date: Fri Sep 29 06:15:08 2006
New Revision: 451279

URL: http://svn.apache.org/viewvc?view=rev&rev=451279
Log:
* Move the tasks of eor_bucket_destroy (status update, transaction logging) to
  a cleanup function that is registered with the request pool.
  eor_bucket_destroy only destroys the request pool if there is still a request
  at this point of time which triggers the call of the cleanup function.

  This is needed as the eor bucket could be (and usually is) allocated from
  a pool different from the request pool (the connection pool in this case).
  This can lead to situations where eor_bucket_destroy is called at a point of
  time when the request pool had been already destroyed. But the status update
  and the transaction logging rely on the request pool.

  In practise this happens with the worker MPM if the client refuses to read
  the response from the handler. Then the unsent data (including the
  eor bucket) remains in a brigade allocated from the connection pool which
  is the parent of the request pool. This brigade is cleaned up during the
  cleanup of the ptrans pool in worker_thread. As the request pool gets
  destroyed during this cleanup operation *before* the brigade gets cleaned up
  eor_bucket_destroy starts the status update and the transaction logging with
  a destroyed request pool which leads to a segfault.

Modified:
    httpd/httpd/trunk/server/eor_bucket.c

Modified: httpd/httpd/trunk/server/eor_bucket.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/eor_bucket.c?view=diff&rev=451279&r1=451278&r2=451279
==============================================================================
--- httpd/httpd/trunk/server/eor_bucket.c (original)
+++ httpd/httpd/trunk/server/eor_bucket.c Fri Sep 29 06:15:08 2006
@@ -19,6 +19,27 @@
 #include "http_protocol.h"
 #include "scoreboard.h"
 
+static apr_status_t eor_bucket_cleanup(void *data)
+{
+    apr_bucket *b = (apr_bucket *)data;
+    request_rec *r = (request_rec *)b->data;
+
+    if (r != NULL) {
+        /*
+         * If eor_bucket_destroy is called after us, this prevents
+         * eor_bucket_destroy from trying to destroy the pool again.
+         */
+        b->data = NULL;
+        /* Update child status and log the transaction */
+        ap_update_child_status(r->connection->sbh, SERVER_BUSY_LOG, r);
+        ap_run_log_transaction(r);
+        if (ap_extended_status) {
+            ap_increment_counts(r->connection->sbh, r);
+        }
+    }
+    return APR_SUCCESS;
+}
+
 static apr_status_t eor_bucket_read(apr_bucket *b, const char **str,
                                     apr_size_t *len, apr_read_type_e block)
 {
@@ -45,18 +66,26 @@
     APR_BUCKET_INIT(b);
     b->free = apr_bucket_free;
     b->list = list;
+    if (r) {
+        /*
+         * Register a cleanup for the request pool as the eor bucket could
+         * have been allocated from a different pool then the request pool
+         * e.g. the parent pool of the request pool. In this case
+         * eor_bucket_destroy might be called at a point of time when the
+         * request pool had been already destroyed.
+         */
+        apr_pool_cleanup_register(r->pool, (void *)b, eor_bucket_cleanup,
+                                  apr_pool_cleanup_null);
+    }
     return ap_bucket_eor_make(b, r);
 }
 
 static void eor_bucket_destroy(void *data)
 {
     request_rec *r = (request_rec *)data;
-    if (r != NULL) {
-        ap_update_child_status(r->connection->sbh, SERVER_BUSY_LOG, r);
-        ap_run_log_transaction(r);
-        if (ap_extended_status) {
-            ap_increment_counts(r->connection->sbh, r);
-        }
+
+    if (r) {
+        /* eor_bucket_cleanup will be called when the pool gets destroyed */
         apr_pool_destroy(r->pool);
     }
 }



Mime
View raw message