diff options
author | Giovanni Bechis <gbechis@apache.org> | 2023-06-07 00:02:37 +0200 |
---|---|---|
committer | Giovanni Bechis <gbechis@apache.org> | 2023-06-07 00:02:37 +0200 |
commit | e466de0c0ca858be2d5bc1ebb446ef4b4dd0a4e6 (patch) | |
tree | 136475a861ca4244e228b32e131b721c26e217dd /modules/filters | |
parent | there is a separate `connectiontimeout` (diff) | |
download | apache2-e466de0c0ca858be2d5bc1ebb446ef4b4dd0a4e6.tar.xz apache2-e466de0c0ca858be2d5bc1ebb446ef4b4dd0a4e6.zip |
mod_ext_filter: check exit status of filter processes
Whenever a filter process returns a non-zero exit status, or is killed
by a signal, return a HTTP 500 error, and log the reason.
Ran top-level make update-log-msg-tags to update APLOGNO numbers.
Submitted by: Dimitry Andric <dimitry@unified-streaming.com>
Github: closes #296
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1910267 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/filters')
-rw-r--r-- | modules/filters/mod_ext_filter.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/modules/filters/mod_ext_filter.c b/modules/filters/mod_ext_filter.c index cb987c3aa5..3944847c8d 100644 --- a/modules/filters/mod_ext_filter.c +++ b/modules/filters/mod_ext_filter.c @@ -726,6 +726,40 @@ static apr_status_t pass_data_to_filter(ap_filter_t *f, const char *data, return rv; } +/* check_filter_process_on_eos(): + * + * if we hit end-of-stream, check the exit status of the filter process, and log + * an appropriate message if it failed + */ +static apr_status_t check_filter_process_on_eos(ef_ctx_t *ctx, request_rec *r) +{ + if (ctx->hit_eos) { + int exitcode; + apr_exit_why_e exitwhy; + apr_status_t waitret = apr_proc_wait(ctx->proc, &exitcode, &exitwhy, + APR_WAIT); + if (waitret != APR_CHILD_DONE) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, waitret, r, APLOGNO(10451) + "apr_proc_wait() failed, uri=%s", r->uri); + return waitret; + } + else if (exitwhy != APR_PROC_EXIT) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(10452) + "child process %s killed by signal %d, uri=%s", + ctx->filter->command, exitcode, r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + else if (exitcode != 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, APLOGNO(10453) + "child process %s exited with non-zero status %d, " + "uri=%s", ctx->filter->command, exitcode, r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + } + + return APR_SUCCESS; +} + /* ef_unified_filter: * * runs the bucket brigade bb through the filter and puts the result into @@ -880,6 +914,11 @@ static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01468) "ef_unified_filter() failed"); + return rv; + } + + if ((rv = check_filter_process_on_eos(ctx, r)) != APR_SUCCESS) { + return rv; } if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { @@ -939,7 +978,13 @@ static apr_status_t ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, } rv = ef_unified_filter(f, bb); - return rv; + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, APLOGNO(10454) + "ef_unified_filter() failed"); + return rv; + } + + return check_filter_process_on_eos(ctx, f->r); } AP_DECLARE_MODULE(ext_filter) = |