Commit 8b6552af authored by Ruediger Pluem's avatar Ruediger Pluem
Browse files

* Correctly signal broken backend connections up the chain also for the ajp

  backend (see also r357461). Furthermore move common code in mod_proxy_http.c
  and mod_proxy_ajp.c into a new function (ap_proxy_backend_broke) in
  proxy_util.c.

  modules/proxy/mod_proxy_ajp.c : Signal broken backend connection for ajp backend
  modules/proxy/proxy_util.c    : Add ap_proxy_backend_broke
  modules/proxy/mod_proxy_http.c: - Use ap_proxy_backend_broke
                                  - Return DONE also if backend broke
  modules/proxy/mod_proxy.h     : Add declaration of ap_proxy_backend_broke


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@365374 13f79535-47bb-0310-9956-ffa450edef68
parent 12e9973d
Loading
Loading
Loading
Loading
+9 −0
Changes for modules/proxy/mod_proxy.h: 9 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -669,6 +669,15 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
                                              proxy_conn_rec *conn,
                                              conn_rec *c, server_rec *s);
/**
 * Signal the upstream chain that the connection to the backend broke in the
 * middle of the response. This is done by sending an error bucket with
 * status HTTP_BAD_GATEWAY and an EOS bucket up the filter chain.
 * @param r       current request record of client request
 * @param brigade The brigade that is sent through the output filter chain
 */
PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
                                           apr_bucket_brigade *brigade);

/* Scoreboard */
#if MODULE_MAGIC_NUMBER_MAJOR > 20020903
+38 −2
Changes for modules/proxy/mod_proxy_ajp.c: 38 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -138,6 +138,8 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
    int havebody = 1;
    int isok = 1;
    apr_off_t bb_len;
    int data_sent = 0;
    int rv = 0;
#ifdef FLUSHING_BANDAID
    apr_int32_t conn_poll_fd;
    apr_pollfd_t *conn_poll;
@@ -348,6 +350,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
                                      "proxy: error processing body");
                        isok = 0;
                    }
                    data_sent = 1;
                    apr_brigade_cleanup(output_brigade);
                }
                else {
@@ -363,6 +366,7 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
                                  "proxy: error processing body");
                    isok = 0;
                }
                data_sent = 1;
                break;
            default:
                isok = 0;
@@ -400,7 +404,11 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
    }
    apr_brigade_destroy(input_brigade);

    apr_brigade_destroy(output_brigade);
    /*
     * Clear output_brigade to remove possible buckets that remained there
     * after an error.
     */
    apr_brigade_cleanup(output_brigade);

    if (status != APR_SUCCESS) {
        /* We had a failure: Close connection to backend */
@@ -409,9 +417,37 @@ static int ap_proxy_ajp_request(apr_pool_t *p, request_rec *r,
                     "proxy: send body failed to %pI (%s)",
                     conn->worker->cp->addr,
                     conn->worker->hostname);
        return HTTP_SERVICE_UNAVAILABLE;
        /*
         * If we already send data, signal a broken backend connection
         * upwards in the chain.
         */
        if (data_sent) {
            ap_proxy_backend_broke(r, output_brigade);
            /* Return DONE to avoid error messages being added to the stream */
            rv = DONE;
        } else
            rv = HTTP_SERVICE_UNAVAILABLE;
    }

    /*
     * Ensure that we sent an EOS bucket thru the filter chain, if we already
     * have sent some data. Maybe ap_proxy_backend_broke was called and added
     * one to the brigade already. So we should not do this in this case.
     */
    if (data_sent && !r->eos_sent && APR_BRIGADE_EMPTY(output_brigade)) {
        e = apr_bucket_eos_create(r->connection->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(output_brigade, e);
    }

    /* If we have added something to the brigade above, sent it */
    if (!APR_BRIGADE_EMPTY(output_brigade))
        ap_pass_brigade(r->output_filters, output_brigade);

    apr_brigade_destroy(output_brigade);

    if (rv)
        return rv;

    /* Nice we have answer to send to the client */
    if (result == CMD_AJP13_END_RESPONSE && isok) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+4 −7
Changes for modules/proxy/mod_proxy_http.c: 4 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -1199,6 +1199,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                           * are being read. */
    int pread_len = 0;
    apr_table_t *save_table;
    int backend_broke = 0;

    bb = apr_brigade_create(p, c->bucket_alloc);

@@ -1486,13 +1487,9 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
                         */
                        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c,
                                      "proxy: error reading response");
                        r->no_cache = 1;
                        e = ap_bucket_error_create(HTTP_BAD_GATEWAY,  NULL,
                                                   c->pool, c->bucket_alloc);
                        APR_BRIGADE_INSERT_TAIL(bb, e);
                        e = apr_bucket_eos_create(c->bucket_alloc);
                        APR_BRIGADE_INSERT_TAIL(bb, e);
                        ap_proxy_backend_broke(r, bb);
                        ap_pass_brigade(r->output_filters, bb);
                        backend_broke = 1;
                        backend->close = 1;
                        break;
                    }
@@ -1560,7 +1557,7 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
    } while (interim_response);

    /* If our connection with the client is to be aborted, return DONE. */
    if (c->aborted) {
    if (c->aborted || backend_broke) {
        return DONE;
    }

+14 −0
Changes for modules/proxy/proxy_util.c: 14 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -2129,3 +2129,17 @@ int ap_proxy_lb_workers(void)
    lb_workers_limit = proxy_lb_workers + PROXY_DYNAMIC_BALANCER_LIMIT;
    return lb_workers_limit;
}

PROXY_DECLARE(void) ap_proxy_backend_broke(request_rec *r,
                                           apr_bucket_brigade *brigade)
{
    apr_bucket *e;
    conn_rec *c = r->connection;

    r->no_cache = 1;
    e = ap_bucket_error_create(HTTP_BAD_GATEWAY, NULL, c->pool,
                               c->bucket_alloc);
    APR_BRIGADE_INSERT_TAIL(brigade, e);
    e = apr_bucket_eos_create(c->bucket_alloc);
    APR_BRIGADE_INSERT_TAIL(brigade, e);
}