Skip to content

Instantly share code, notes, and snippets.

@adsr
Created January 13, 2022 21:11
Show Gist options
  • Save adsr/0442cce8f420fe4340832f7d7c05eefe to your computer and use it in GitHub Desktop.
Save adsr/0442cce8f420fe4340832f7d7c05eefe to your computer and use it in GitHub Desktop.
diff --git a/main/main.c b/main/main.c
index a0f1a658c6..65fa68f682 100644
--- a/main/main.c
+++ b/main/main.c
@@ -673,20 +673,21 @@ PHP_INI_BEGIN()
PHP_INI_ENTRY_EX("highlight.comment", HL_COMMENT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.default", HL_DEFAULT_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.html", HL_HTML_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.keyword", HL_KEYWORD_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
PHP_INI_ENTRY_EX("highlight.string", HL_STRING_COLOR, PHP_INI_ALL, NULL, php_ini_color_displayer_cb)
STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL, OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode)
STD_PHP_INI_BOOLEAN("display_startup_errors", "1", PHP_INI_ALL, OnUpdateBool, display_startup_errors, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("enable_dl", "1", PHP_INI_SYSTEM, OnUpdateBool, enable_dl, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("expose_php", "1", PHP_INI_SYSTEM, OnUpdateBool, expose_php, php_core_globals, core_globals)
+ STD_PHP_INI_ENTRY("warmup_script", "", PHP_INI_ALL, OnUpdateString, warmup_script, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("docref_root", "", PHP_INI_ALL, OnUpdateString, docref_root, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("docref_ext", "", PHP_INI_ALL, OnUpdateString, docref_ext, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("html_errors", "1", PHP_INI_ALL, OnUpdateBool, html_errors, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("xmlrpc_errors", "0", PHP_INI_SYSTEM, OnUpdateBool, xmlrpc_errors, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("xmlrpc_error_number", "0", PHP_INI_ALL, OnUpdateLong, xmlrpc_error_number, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("max_input_time", "-1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, max_input_time, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("ignore_user_abort", "0", PHP_INI_ALL, OnUpdateBool, ignore_user_abort, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("implicit_flush", "0", PHP_INI_ALL, OnUpdateBool, implicit_flush, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("log_errors", "0", PHP_INI_ALL, OnUpdateBool, log_errors, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("ignore_repeated_errors", "0", PHP_INI_ALL, OnUpdateBool, ignore_repeated_errors, php_core_globals, core_globals)
diff --git a/main/php_globals.h b/main/php_globals.h
index 80152663f4..0027f2bb0c 100644
--- a/main/php_globals.h
+++ b/main/php_globals.h
@@ -104,20 +104,22 @@ struct _php_core_globals {
bool ignore_user_abort;
unsigned char header_is_being_sent;
zend_llist tick_functions;
zval http_globals[6];
bool expose_php;
+ char *warmup_script;
+
bool register_argc_argv;
bool auto_globals_jit;
char *docref_root;
char *docref_ext;
bool html_errors;
bool xmlrpc_errors;
zend_long xmlrpc_error_number;
diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c
index 7933e6acce..a450ff19e1 100644
--- a/sapi/apache2handler/sapi_apache2.c
+++ b/sapi/apache2handler/sapi_apache2.c
@@ -584,39 +584,47 @@ static int php_handler(request_rec *r)
#ifdef ZTS
/* initial resource fetch */
(void)ts_resource(0);
# ifdef PHP_WIN32
ZEND_TSRMLS_CACHE_UPDATE();
# endif
#endif
#define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req);
- conf = ap_get_module_config(r->per_dir_config, &php_module);
+ /* Eh difficult to mock this struct */
+ if (r->per_dir_config) {
+ conf = ap_get_module_config(r->per_dir_config, &php_module);
+ } else {
+ conf = NULL;
+ }
/* apply_config() needs r in some cases, so allocate server_context early */
ctx = SG(server_context);
if (ctx == NULL || (ctx && ctx->request_processed && !strcmp(r->protocol, "INCLUDED"))) {
normal:
ctx = SG(server_context) = apr_pcalloc(r->pool, sizeof(*ctx));
/* register a cleanup so we clear out the SG(server_context)
* after each request. Note: We pass in the pointer to the
* server_context in case this is handled by a different thread.
*/
apr_pool_cleanup_register(r->pool, (void *)&SG(server_context), php_server_context_cleanup, apr_pool_cleanup_null);
ctx->r = r;
ctx = NULL; /* May look weird to null it here, but it is to catch the right case in the first_try later on */
} else {
parent_req = ctx->r;
ctx->r = r;
}
- apply_config(conf);
+
+ if (conf) {
+ apply_config(conf);
+ }
if (strcmp(r->handler, PHP_MAGIC_TYPE) && strcmp(r->handler, PHP_SOURCE_MAGIC_TYPE) && strcmp(r->handler, PHP_SCRIPT)) {
/* Check for xbithack in this case. */
if (!AP2(xbithack) || strcmp(r->handler, "text/html") || !(r->finfo.protection & APR_UEXECUTE)) {
PHPAP_INI_OFF;
return DECLINED;
}
}
/* Give a 404 if PATH_INFO is used but is explicitly disabled in
@@ -734,23 +742,65 @@ zend_first_try {
}
apr_brigade_cleanup(brigade);
apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup);
} else {
ctx->r = parent_req;
}
return OK;
}
+static void php_apache_child_warmup(apr_pool_t *pchild, server_rec *s)
+{
+ apr_pool_t *ptemp;
+ php_struct *ctx;
+ zend_file_handle zfd;
+ char *warmup_script;
+
+ warmup_script = NULL;
+ cfg_get_string("warmup_script", &warmup_script);
+
+ if (!warmup_script || !*warmup_script) {
+ return;
+ }
+
+ php_apache_sapi_log_message("Running warmup request", LOG_NOTICE);
+
+ apr_pool_create(&ptemp, pchild);
+
+ /* Hacky. Did not find a way to cleanly make a request struct separate from
+ * doing network */
+ ctx = apr_pcalloc(ptemp, sizeof(*ctx));
+ ctx->r = apr_pcalloc(ptemp, sizeof(*ctx->r));
+ ctx->r->pool = ptemp;
+ ctx->r->headers_in = apr_table_make(ptemp, 0);
+ ctx->r->headers_out = apr_table_make(ptemp, 0);
+ SG(server_context) = ctx;
+
+zend_first_try {
+ zend_stream_init_filename(&zfd, warmup_script);
+ zfd.primary_script = 1;
+
+ php_request_startup();
+ php_execute_script(&zfd);
+ php_request_shutdown(NULL);
+
+ zend_destroy_file_handle(&zfd);
+} zend_end_try();
+
+ apr_pool_destroy(ptemp);
+}
+
static void php_apache_child_init(apr_pool_t *pchild, server_rec *s)
{
- apr_pool_cleanup_register(pchild, NULL, php_apache_child_shutdown, apr_pool_cleanup_null);
+ apr_pool_cleanup_register(pchild, NULL, php_apache_child_shutdown, apr_pool_cleanup_null);
+ php_apache_child_warmup(pchild, s);
}
#ifdef ZEND_SIGNALS
static void php_apache_signal_init(apr_pool_t *pchild, server_rec *s)
{
zend_signal_init();
}
#endif
void php_ap2_register_hook(apr_pool_t *p)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment