]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Backport r731358/731388/731594
authorNick Kew <niq@apache.org>
Thu, 8 Jan 2009 01:39:02 +0000 (01:39 +0000)
committerNick Kew <niq@apache.org>
Thu, 8 Jan 2009 01:39:02 +0000 (01:39 +0000)
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
STATUS
docs/manual/mod/mod_ext_filter.xml
modules/filters/mod_ext_filter.c

diff --git a/CHANGES b/CHANGES
index 32e9433c75eebde6f3f312513ed650551c6c532b..f28a4ecd593f72bac252e897a2169709391cdbb0 100644 (file)
--- 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 5f20e87bb7f787b6580fb99d4c3b457ca4cad061..ebb667a928838de4fa02517ea0c8d813f41f081d 100644 (file)
--- 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 ]
 
index 68fdfea9221b9dc1af300678813155ad6d21dd7a..f3af4062d5820f937dd3e2af3986a4b7959e9eaa 100644 (file)
@@ -340,6 +340,12 @@ delivery to the client</description>
       messages written to standard error by the external filter
       program will be saved in the Apache error log.
       <code>NoLogStderr</code> disables this feature.</dd>
+
+      <dt><code>Onfail=[abort|remove]</code> (new in httpd version 2.2.12).</dt>
+      <dd>Determines how to proceed if the external filter program
+      cannot be started.  With <code>abort</code> (the default value)
+      the request will be aborted.  With <code>remove</code>, the
+      filter is removed and the request continues without it.</dd>
     </dl>
 
     <example><title>Example</title>
index 78c9f90d5efd2a284ad93457f927b0b7b437c128..fe92271625e5b1ccce7d42f010e0e71b40312c84 100644 (file)
@@ -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;
     }