That is, not only when a hook/handler returns AP_FILTER_ERROR.
Graham (initially) and I made some changes to trunk (backport proposed
in r1665737) so that no internal module should return anything but
AP_FILTER_ERROR in this case, but we can't do much for third-party
modules.
That way ap_die() could become a safe gard against unintentional
double responses (hence HRS) for the same request, in any case since
it is always called at the end.
Something like:
Index: modules/http/http_request.c
===================================================================
--- modules/http/http_request.c (revision 1665647)
+++ modules/http/http_request.c (working copy)
@@ -75,6 +75,7 @@ static void update_r_in_filters(ap_filter_t *f,
static void ap_die_r(int type, request_rec *r, int recursive_error)
{
+ ap_filter_t *next;
char *custom_response;
request_rec *r_1st_err = r;
@@ -83,38 +84,34 @@ static void ap_die_r(int type, request_rec *r, int
return;
}
+ /*
+ * Check if we still have the ap_http_header_filter in place. If
+ * this is the case we should not ignore the error here because
+ * it means that we have not sent any response at all. Otherwise,
+ * don't send two responses for the same request.
+ */
+ next = r->output_filters;
+ while (next && (next->frec != ap_http_header_filter_handle)) {
+ next = next->next;
+ }
+ if (!next) {
+ return;
+ }
+
+ /*
+ * AP_FILTER_ERROR or any invalid status, send an internal server
+ * error instead.
+ */
if (!ap_is_HTTP_VALID_RESPONSE(type)) {
- ap_filter_t *next;
-
- /*
- * Check if we still have the ap_http_header_filter in place. If
- * this is the case we should not ignore the error here because
- * it means that we have not sent any response at all and never
- * will. This is bad. Sent an internal server error instead.
- */
- next = r->output_filters;
- while (next && (next->frec != ap_http_header_filter_handle)) {
- next = next->next;
- }
-
- /*
- * If next != NULL then we left the while above because of
- * next->frec == ap_http_header_filter
- */
- if (next) {
- if (type != AP_FILTER_ERROR) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01579)
- "Invalid response status %i", type);
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02831)
- "Response from AP_FILTER_ERROR");
- }
- type = HTTP_INTERNAL_SERVER_ERROR;
- }
- else {
- return;
- }
+ if (type != AP_FILTER_ERROR) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01579)
+ "Invalid response status %i", type);
+ }
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02831)
+ "Response from AP_FILTER_ERROR");
+ }
+ type = HTTP_INTERNAL_SERVER_ERROR;
}
/*
--
This is not a great cycles loss since this path is not a fast one
already (!OK && !DONE => ap_send_error_response() or
ap_internal_redirect()), and the inconditional loop is not really
heavy...
Thoughts?
Regards,
Yann.