Commit b156c592 authored by Yann Ylavic's avatar Yann Ylavic
Browse files

core: always allocate filters (ap_filter_t) on f->c->pool.

When filters are allocated on f->r->pool, they may be destroyed any time
underneath themselves which makes it hard for them to be passed the EOR and
forward it (*f can't be dereferenced anymore when the EOR is destroyed, thus
before request filters return).

On the util_filter side, it also makes it impossible to flush pending request
filters when they have set aside the EOR, since f->bb can't be accessed after
it's passed to the f->next.

So we always use f->c->pool to allocate filters and pending brigades, and to
avoid leaks with keepalive requests (long living connections handling multiple
requests), filters and brigades are recycled with a cleanup on f->r->pool.

Recycling is done (generically) with a spare data ring (void pointers), and a
filter(s) context struct is associated with the conn_rec to maintain the rings
by connection, that is:

    struct ap_filter_conn_ctx {
        struct ap_filter_ring *pending_input_filters;
        struct ap_filter_ring *pending_output_filters;

        struct ap_filter_spare_ring *spare_containers,
                                    *spare_brigades,
                                    *spare_filters,
                                    *spare_flushes;
        int flushing;
    };

MMN major bumped (again).


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1839997 13f79535-47bb-0310-9956-ffa450edef68
parent c1b278a3
Loading
Loading
Loading
Loading
+4 −2
Changes for include/ap_mmn.h: 4 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -598,13 +598,15 @@
 * 20180720.7 (2.5.1-dev)  worker_share struct re-organized
 * 20180902.1 (2.5.1-dev)  Split conn_rec pending_filters in two rings,
 *                         pending_input_filters and pending_output_filters
 *
 * 20180903.1 (2.5.1-dev)  Replace conn_rec pending_{in,out}put_filters by
 *                         filter_conn_ctx, remove argument pool from
 *                         ap_filter_prepare_brigade()
 */

#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */

#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20180902
#define MODULE_MAGIC_NUMBER_MAJOR 20180903
#endif
#define MODULE_MAGIC_NUMBER_MINOR 1                 /* 0...n */

+3 −5
Changes for include/httpd.h: 3 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -1111,7 +1111,7 @@ typedef enum {
    AP_CONN_KEEPALIVE
} ap_conn_keepalive_e;

/* For struct ap_filter and ap_filter_ring */
/* For struct ap_filter_conn_ctx */
#include "util_filter.h"

/**
@@ -1224,10 +1224,8 @@ struct conn_rec {
    /** Array of requests being handled under this connection. */
    apr_array_header_t *requests;

    /** Ring of pending input filters (with setaside buckets) */
    struct ap_filter_ring *pending_input_filters;
    /** Ring of pending output filters (with setaside buckets) */
    struct ap_filter_ring *pending_output_filters;
    /** Filters' context for this connection */
    struct ap_filter_conn_ctx *filter_conn_ctx;

    /** The minimum level of filter type to allow setaside buckets */
    int async_filter;
+3 −6
Changes for include/util_filter.h: 3 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -304,9 +304,9 @@ struct ap_filter_t {
};

/**
 * @brief The type of a filters' ring (opaque).
 * @brief The filters' context in conn_rec (opaque).
 */
typedef struct ap_filter_ring ap_filter_ring_t;
struct ap_filter_conn_ctx;

/**
 * Get the current bucket brigade from the next filter on the filter
@@ -569,12 +569,9 @@ AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
 * filters, or can be used within an output filter by being called via
 * ap_filter_setaside_brigade().
 * @param f The current filter
 * @param p The pool that was used to create the brigade. In a request
 * filter this will be the request pool, in a connection filter this will
 * be the connection pool.
 * @returns OK if a brigade was created, DECLINED otherwise.
 */
AP_DECLARE(int) ap_filter_prepare_brigade(ap_filter_t *f, apr_pool_t **p);
AP_DECLARE(int) ap_filter_prepare_brigade(ap_filter_t *f);

/**
 * Prepare a bucket brigade to be setaside, creating a dedicated pool if
+1 −0
Changes for modules/http2/h2_conn.c: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -313,6 +313,7 @@ conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent)
    c->notes                  = apr_table_make(pool, 5);
    c->input_filters          = NULL;
    c->output_filters         = NULL;
    c->filter_conn_ctx        = NULL;
    c->bucket_alloc           = apr_bucket_alloc_create(pool);
    /* prevent mpm_event from making wrong assumptions about this connection,
     * like e.g. using its socket for an async read check. */
+3 −4
Changes for modules/ssl/ssl_engine_io.c: 3 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -1813,7 +1813,7 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f,

        /* if the core has set aside data, back off and try later */
        if (!flush_upto) {
            if (ap_filter_should_yield(f)) {
            if (ap_filter_should_yield(f->next)) {
                break;
            }
        }
@@ -1869,10 +1869,9 @@ static apr_status_t ssl_io_filter_output(ap_filter_t *f,

    }

    if (APR_STATUS_IS_EOF(status) || (status == APR_SUCCESS)) {
        return ap_filter_setaside_brigade(f, bb);
    if (status == APR_SUCCESS) {
        status = ap_filter_setaside_brigade(f, bb);
    }

    return status;
}

Loading