Created
October 21, 2017 20:10
-
-
Save adsr/d5015ae37f8a080dcf5bac428f7fdee0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/server/config.c b/server/config.c | |
index 7c7a1e0033..754152b86b 100644 | |
--- a/server/config.c | |
+++ b/server/config.c | |
@@ -45,37 +45,42 @@ | |
#include "http_protocol.h" | |
#include "http_core.h" | |
#include "http_log.h" /* for errors in parse_htaccess */ | |
#include "http_request.h" /* for default_handler (see invoke_handler) */ | |
#include "http_main.h" | |
#include "http_vhost.h" | |
#include "util_cfgtree.h" | |
#include "util_varbuf.h" | |
#include "mpm_common.h" | |
+#include "setjmp.h" | |
+#include "apr_signal.h" | |
+ | |
#define APLOG_UNSET (APLOG_NO_MODULE - 1) | |
/* we know core's module_index is 0 */ | |
#undef APLOG_MODULE_INDEX | |
#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX | |
AP_DECLARE_DATA const char *ap_server_argv0 = NULL; | |
AP_DECLARE_DATA const char *ap_server_root = NULL; | |
AP_DECLARE_DATA const char *ap_runtime_dir = NULL; | |
AP_DECLARE_DATA server_rec *ap_server_conf = NULL; | |
AP_DECLARE_DATA apr_pool_t *ap_pglobal = NULL; | |
AP_DECLARE_DATA apr_array_header_t *ap_server_pre_read_config = NULL; | |
AP_DECLARE_DATA apr_array_header_t *ap_server_post_read_config = NULL; | |
AP_DECLARE_DATA apr_array_header_t *ap_server_config_defines = NULL; | |
AP_DECLARE_DATA ap_directive_t *ap_conftree = NULL; | |
+AP_DECLARE_DATA sigjmp_buf ap_invoke_handler_jmpenv; | |
+ | |
APR_HOOK_STRUCT( | |
APR_HOOK_LINK(header_parser) | |
APR_HOOK_LINK(pre_config) | |
APR_HOOK_LINK(check_config) | |
APR_HOOK_LINK(post_config) | |
APR_HOOK_LINK(open_logs) | |
APR_HOOK_LINK(child_init) | |
APR_HOOK_LINK(handler) | |
APR_HOOK_LINK(quick_handler) | |
APR_HOOK_LINK(optional_fn_retrieve) | |
@@ -370,20 +375,25 @@ static int invoke_filter_init(request_rec *r, ap_filter_t *filters) | |
int result = filters->frec->filter_init_func(filters); | |
if (result != OK) { | |
return result; | |
} | |
} | |
filters = filters->next; | |
} | |
return OK; | |
} | |
+static void ap_invoke_handler_timeout(int sig) | |
+{ | |
+ siglongjmp(ap_invoke_handler_jmpenv, 1); | |
+} | |
+ | |
AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r) | |
{ | |
const char *handler; | |
const char *p; | |
int result; | |
const char *old_handler = r->handler; | |
const char *ignore; | |
/* | |
* The new insert_filter stage makes the most sense here. We only use | |
@@ -424,22 +434,44 @@ AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r) | |
*p2='\0'; | |
} | |
} | |
else { | |
handler = AP_DEFAULT_HANDLER_NAME; | |
} | |
r->handler = handler; | |
} | |
- result = ap_run_handler(r); | |
+ struct itimerval ntimer; | |
+ struct sigaction sigact; | |
+ int jmpv; | |
+ jmpv = sigsetjmp(ap_invoke_handler_jmpenv, 1); | |
+ if (jmpv == 0) { | |
+ // Timeout after 50ms | |
+ ntimer.it_interval.tv_sec = 0; | |
+ ntimer.it_interval.tv_usec = 0; | |
+ ntimer.it_value.tv_sec = 0; | |
+ ntimer.it_value.tv_usec = 50 * 1000; | |
+ setitimer(ITIMER_REAL, &ntimer, NULL); | |
+ | |
+ // Install signal handler | |
+ apr_signal(SIGALRM, ap_invoke_handler_timeout); | |
+ | |
+ // Run handler | |
+ result = ap_run_handler(r); | |
+ apr_signal(SIGALRM, SIG_IGN); | |
+ } else { | |
+ // Timed out; clear signal handler | |
+ apr_signal(SIGALRM, SIG_IGN); | |
+ result = HTTP_GATEWAY_TIME_OUT; | |
+ } | |
r->handler = old_handler; | |
if (result == DECLINED && r->handler && r->filename) { | |
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00523) | |
"handler \"%s\" not found for: %s", r->handler, r->filename); | |
} | |
if ((result != OK) && (result != DONE) && (result != DECLINED) && (result != SUSPENDED) | |
&& (result != AP_FILTER_ERROR) /* ap_die() knows about this specifically */ | |
&& !ap_is_HTTP_VALID_RESPONSE(result)) { | |
/* If a module is deliberately returning something else |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Shitty proof of concept. Works with mpm=prefork only. Might be able to generalize for mpm=event etc using timerfd* or signalfd*.