From 76a96f20111921cd63facf4154977c4414b9a016 Mon Sep 17 00:00:00 2001 From: Nick Kew Date: Thu, 8 Jan 2009 01:39:02 +0000 Subject: [PATCH] Backport r731358/731388/731594 mod_ext_filter: introduce sane error handling when the filter program fails to start, including an onfail configuration option. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@732586 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 5 +++ STATUS | 7 ---- docs/manual/mod/mod_ext_filter.xml | 6 +++ modules/filters/mod_ext_filter.c | 60 +++++++++++++++++++++++++++--- 4 files changed, 65 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 32e9433c75e..f28a4ecd593 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,11 @@ -*- coding: utf-8 -*- Changes with Apache 2.2.12 + *) mod_ext_filter: fix error handling when the filter prog fails to start, + and introduce an onfail configuration option to abort the request + or to remove the broken filter and continue. + PR 41120 [Nick Kew] + *) mod_include: support generating non-ASCII characters as entities in SSI PR 25202 [Nick Kew] diff --git a/STATUS b/STATUS index 5f20e87bb7f..ebb667a9288 100644 --- a/STATUS +++ b/STATUS @@ -86,13 +86,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * mod_ext_filter: fix error handling when the filter prog fails to start. - PR 41120 - http://svn.apache.org/viewvc?view=rev&revision=731358 - http://svn.apache.org/viewvc?view=rev&revision=731388 - http://svn.apache.org/viewvc?view=rev&revision=731594 - +1: niq, rpluem, covener - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ New proposals should be added at the end of the list ] diff --git a/docs/manual/mod/mod_ext_filter.xml b/docs/manual/mod/mod_ext_filter.xml index 68fdfea9221..f3af4062d58 100644 --- a/docs/manual/mod/mod_ext_filter.xml +++ b/docs/manual/mod/mod_ext_filter.xml @@ -340,6 +340,12 @@ delivery to the client messages written to standard error by the external filter program will be saved in the Apache error log. NoLogStderr disables this feature. + +
Onfail=[abort|remove] (new in httpd version 2.2.12).
+
Determines how to proceed if the external filter program + cannot be started. With abort (the default value) + the request will be aborted. With remove, the + filter is removed and the request continues without it.
Example diff --git a/modules/filters/mod_ext_filter.c b/modules/filters/mod_ext_filter.c index 78c9f90d5ef..fe92271625e 100644 --- a/modules/filters/mod_ext_filter.c +++ b/modules/filters/mod_ext_filter.c @@ -58,6 +58,7 @@ typedef struct ef_filter_t { typedef struct ef_dir_t { int debug; int log_stderr; + int onfail; } ef_dir_t; typedef struct ef_ctx_t { @@ -81,7 +82,6 @@ static apr_status_t ef_input_filter(ap_filter_t *, apr_bucket_brigade *, apr_off_t); #define DBGLVL_SHOWOPTIONS 1 -#define DBGLVL_ERRORCHECK 2 #define DBGLVL_GORY 9 #define ERRFN_USERDATA_KEY "EXTFILTCHILDERRFN" @@ -92,6 +92,7 @@ static void *create_ef_dir_conf(apr_pool_t *p, char *dummy) dc->debug = -1; dc->log_stderr = -1; + dc->onfail = -1; return dc; } @@ -125,6 +126,13 @@ static void *merge_ef_dir_conf(apr_pool_t *p, void *basev, void *overridesv) a->log_stderr = base->log_stderr; } + if (over->onfail != -1) { /* if admin coded something... */ + a->onfail = over->onfail; + } + else { + a->onfail = base->onfail; + } + return a; } @@ -142,6 +150,12 @@ static const char *add_options(cmd_parms *cmd, void *in_dc, else if (!strcasecmp(arg, "NoLogStderr")) { dc->log_stderr = 0; } + else if (!strcasecmp(arg, "Onfail=remove")) { + dc->onfail = 1; + } + else if (!strcasecmp(arg, "Onfail=abort")) { + dc->onfail = 0; + } else { return apr_pstrcat(cmd->temp_pool, "Invalid ExtFilterOptions option: ", @@ -449,9 +463,9 @@ static apr_status_t init_ext_filter_process(ap_filter_t *f) ap_assert(rc == APR_SUCCESS); apr_pool_userdata_set(f->r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ctx->p); - if (dc->debug >= DBGLVL_ERRORCHECK) { - rc = apr_procattr_error_check_set(ctx->procattr, 1); - ap_assert(rc == APR_SUCCESS); + rc = apr_procattr_error_check_set(ctx->procattr, 1); + if (rc != APR_SUCCESS) { + return rc; } /* add standard CGI variables as well as DOCUMENT_URI, DOCUMENT_PATH_INFO, @@ -855,7 +869,29 @@ static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) if (!ctx) { if ((rv = init_filter_instance(f)) != APR_SUCCESS) { - return rv; + ctx = f->ctx; + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "can't initialise output filter %s: %s", + f->frec->name, + (ctx->dc->onfail == 1) ? "removing" : "aborting"); + ap_remove_output_filter(f); + if (ctx->dc->onfail == 1) { + return ap_pass_brigade(f->next, bb); + } + else { + apr_bucket *e; + f->r->status_line = "500 Internal Server Error"; + + apr_brigade_cleanup(bb); + e = ap_bucket_error_create(HTTP_INTERNAL_SERVER_ERROR, + NULL, r->pool, + f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, e); + e = apr_bucket_eos_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, e); + ap_pass_brigade(f->next, bb); + return AP_FILTER_ERROR; + } } ctx = f->ctx; } @@ -886,7 +922,19 @@ static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, if (!ctx) { if ((rv = init_filter_instance(f)) != APR_SUCCESS) { - return rv; + ctx = f->ctx; + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, + "can't initialise input filter %s: %s", + f->frec->name, + (ctx->dc->onfail == 1) ? "removing" : "aborting"); + ap_remove_input_filter(f); + if (ctx->dc->onfail == 1) { + return ap_get_brigade(f->next, bb, mode, block, readbytes); + } + else { + f->r->status = HTTP_INTERNAL_SERVER_ERROR; + return HTTP_INTERNAL_SERVER_ERROR; + } } ctx = f->ctx; } -- 2.47.2