Here is a new version of my original patch that includes tests (no doc though)
-------------------------------------------------------------------------------- Philippe M. Chiasson m/gozer\@(apache|cpan|ectoplasm)\.org/ GPG KeyID : 88C3A5A5 http://gozer.ectoplasm.org/ F9BF E0C2 480E 7680 1AE5 3631 CB32 A107 88C3A5A5
Index: src/modules/perl/mod_perl.c
===================================================================
--- src/modules/perl/mod_perl.c (revision 112024)
+++ src/modules/perl/mod_perl.c (working copy)
@@ -326,6 +326,10 @@
if (!modperl_config_apply_PerlModule(s, scfg, perl, p)) {
exit(1);
}
+
+ if (!modperl_config_prepare_PerlPostConfigRequire(s, scfg, perl, p)) {
+ exit(1);
+ }
#ifndef USE_ITHREADS
cdata = modperl_cleanup_data_new(server_pool, (void*)perl);
@@ -414,6 +418,10 @@
if (!modperl_config_apply_PerlModule(s, scfg, perl, p)) {
return HTTP_INTERNAL_SERVER_ERROR;
}
+
+ if (!modperl_config_prepare_PerlPostConfigRequire(s, scfg, perl, p)) {
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
}
#ifdef USE_ITHREADS
@@ -466,6 +474,17 @@
}
+static int modperl_post_config_require(server_rec *s, apr_pool_t *p)
+{
+ for (; s; s=s->next) {
+ MP_dSCFG(s);
+ if (!modperl_config_apply_PerlPostConfigRequire(s, scfg, p)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
#ifdef USE_ITHREADS
static void modperl_init_clones(server_rec *s, apr_pool_t *p)
{
@@ -646,6 +665,11 @@
MP_dSCFG(s);
dTHXa(scfg->mip->parent->perl);
#endif
+
+ if (!modperl_post_config_require(s, pconf)) {
+ exit(1);
+ }
+
if (modperl_threaded_mpm()) {
MP_threads_started = 1;
}
@@ -860,6 +884,8 @@
MP_CMD_SRV_ITERATE("PerlSwitches", switches, "Perl Switches"),
MP_CMD_DIR_ITERATE("PerlModule", modules, "PerlModule"),
MP_CMD_DIR_ITERATE("PerlRequire", requires, "PerlRequire"),
+ MP_CMD_SRV_ITERATE("PerlConfigRequire", config_requires, "PerlConfigRequire"),
+ MP_CMD_SRV_ITERATE("PerlPostConfigRequire", post_config_requires, "PerlPostConfigRequire"),
MP_CMD_DIR_ITERATE("PerlOptions", options, "Perl Options"),
MP_CMD_DIR_ITERATE("PerlInitHandler", init_handlers, "Subroutine name"),
MP_CMD_DIR_TAKE2("PerlSetVar", set_var, "PerlSetVar"),
Index: src/modules/perl/modperl_config.c
===================================================================
--- src/modules/perl/modperl_config.c (revision 112024)
+++ src/modules/perl/modperl_config.c (working copy)
@@ -155,6 +155,8 @@
scfg->PerlModule = apr_array_make(p, 2, sizeof(char *));
scfg->PerlRequire = apr_array_make(p, 2, sizeof(char *));
+ scfg->PerlPostConfigRequire =
+ apr_array_make(p, 1, sizeof(modperl_require_file_t *));
scfg->argv = apr_array_make(p, 2, sizeof(char *));
@@ -285,6 +287,7 @@
merge_item(modules);
merge_item(PerlModule);
merge_item(PerlRequire);
+ merge_item(PerlPostConfigRequire);
merge_table_overlap_item(SetEnv);
merge_table_overlap_item(PassEnv);
@@ -437,6 +440,53 @@
return TRUE;
}
+int modperl_config_apply_PerlPostConfigRequire(server_rec *s,
+ modperl_config_srv_t *scfg,
+ apr_pool_t *p)
+{
+ modperl_require_file_t **requires;
+ int i;
+
+ requires = (modperl_require_file_t **)scfg->PerlPostConfigRequire->elts;
+ for (i = 0; i < scfg->PerlPostConfigRequire->nelts; i++){
+ if (modperl_require_file( requires[i]->perl, requires[i]->file, TRUE)){
+ MP_TRACE_d(MP_FUNC, "loaded Perl file: %s for server %s\n",
+ requires[i]->file, modperl_server_desc(s,p));
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+ "Can't load Perl file: %s for server %s, exiting...",
+ requires[i]->file, modperl_server_desc(s,p));
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* In the case where files were added when interpreters were not yet started,
+ * we need to go over the existing files and assign them the correct interpreter
+ */
+int modperl_config_prepare_PerlPostConfigRequire(server_rec *s,
+ modperl_config_srv_t *scfg,
+ PerlInterpreter *perl,
+ apr_pool_t *p)
+{
+ modperl_require_file_t **requires;
+ int i;
+
+ requires = (modperl_require_file_t **)scfg->PerlPostConfigRequire->elts;
+ for (i = 0; i < scfg->PerlPostConfigRequire->nelts; i++) {
+ if (!requires[i]->perl) {
+ MP_TRACE_d(MP_FUNC, "Late binding of %s to an interpreter",
+ requires[i]->file);
+ requires[i]->perl = perl;
+ }
+ }
+
+ return 1;
+}
+
typedef struct {
AV *av;
I32 ix;
Index: src/modules/perl/modperl_types.h
===================================================================
--- src/modules/perl/modperl_types.h (revision 112024)
+++ src/modules/perl/modperl_types.h (working copy)
@@ -65,6 +65,13 @@
};
typedef struct {
+ const char *file;
+#ifdef USE_ITHREADS
+ PerlInterpreter *perl;
+#endif
+} modperl_require_file_t;
+
+typedef struct {
/* s == startup grow
* r == runtime grow
*/
@@ -130,7 +137,7 @@
MpHV *configvars;
MpHV *SetEnv;
MpHV *PassEnv;
- MpAV *PerlRequire, *PerlModule;
+ MpAV *PerlRequire, *PerlModule, *PerlPostConfigRequire;
MpAV *handlers_per_srv[MP_HANDLER_NUM_PER_SRV];
MpAV *handlers_files[MP_HANDLER_NUM_FILES];
MpAV *handlers_process[MP_HANDLER_NUM_PROCESS];
Index: src/modules/perl/modperl_config.h
===================================================================
--- src/modules/perl/modperl_config.h (revision 112024)
+++ src/modules/perl/modperl_config.h (working copy)
@@ -122,6 +122,15 @@
modperl_config_srv_t *scfg,
PerlInterpreter *perl, apr_pool_t *p);
+int modperl_config_prepare_PerlPostConfigRequire(server_rec *s,
+ modperl_config_srv_t *scfg,
+ PerlInterpreter *perl,
+ apr_pool_t *p);
+
+int modperl_config_apply_PerlPostConfigRequire(server_rec *s,
+ modperl_config_srv_t *scfg,
+ apr_pool_t *p);
+
const char *modperl_config_insert(pTHX_ server_rec *s,
apr_pool_t *p,
apr_pool_t *ptmp,
Index: src/modules/perl/modperl_cmd.c
===================================================================
--- src/modules/perl/modperl_cmd.c (revision 112024)
+++ src/modules/perl/modperl_cmd.c (working copy)
@@ -266,6 +266,49 @@
}
}
+MP_CMD_SRV_DECLARE(config_requires)
+{
+ /* we must init earlier than normal */
+ modperl_run();
+
+ /* PerlConfigFile is only different from PerlRequires by forcing
+ * an immediate init.
+ */
+ return modperl_cmd_requires(parms, mconfig, arg);
+}
+
+MP_CMD_SRV_DECLARE(post_config_requires)
+{
+ MP_dSCFG(parms->server);
+ MP_PERL_DECLARE_CONTEXT;
+ apr_pool_t *p = parms->pool;
+ apr_finfo_t finfo;
+
+ if (APR_SUCCESS == apr_stat(&finfo, arg, APR_FINFO_TYPE, p)) {
+ if (finfo.filetype != APR_NOFILE) {
+ modperl_require_file_t *require = apr_pcalloc(p, sizeof(*require));
+#ifdef USE_ITHREADS
+ if (modperl_is_running()) {
+ MP_PERL_OVERRIDE_CONTEXT;
+ require->perl = aTHX;
+ MP_PERL_RESTORE_CONTEXT;
+ }
+#endif
+ require->file = arg;
+
+ MP_TRACE_d(MP_FUNC, "push PerlPostConfigRequire for %s\n", arg);
+
+ *(modperl_require_file_t **)
+ apr_array_push(scfg->PerlPostConfigRequire) = require;
+ }
+ }
+ else {
+ return apr_pstrcat(p, "No such file : ", arg, NULL);
+ }
+
+ return NULL;
+}
+
static void modperl_cmd_addvar_func(apr_table_t *configvars,
apr_table_t *setvars,
const char *key, const char *val)
Index: src/modules/perl/modperl_cmd.h
===================================================================
--- src/modules/perl/modperl_cmd.h (revision 112024)
+++ src/modules/perl/modperl_cmd.h (working copy)
@@ -39,6 +39,8 @@
MP_CMD_SRV_DECLARE(switches);
MP_CMD_SRV_DECLARE(modules);
MP_CMD_SRV_DECLARE(requires);
+MP_CMD_SRV_DECLARE(config_requires);
+MP_CMD_SRV_DECLARE(post_config_requires);
MP_CMD_SRV_DECLARE2(set_var);
MP_CMD_SRV_DECLARE2(add_var);
MP_CMD_SRV_DECLARE2(set_env);
Index: t/htdocs/vhost/post_config.pl
===================================================================
--- t/htdocs/vhost/post_config.pl (revision 0)
+++ t/htdocs/vhost/post_config.pl (revision 0)
@@ -0,0 +1,9 @@
+use warnings;
+use strict;
+
+use Apache2;
+use Apache::ServerUtil ();
+
+$TestVhost::config::Restart_Count = Apache::ServerUtil::restart_count();
+
+1;
Index: t/conf/modperl_extra.pl
===================================================================
--- t/conf/modperl_extra.pl (revision 112024)
+++ t/conf/modperl_extra.pl (working copy)
@@ -33,8 +33,6 @@
reorg_INC();
-register_post_config_startup();
-
startup_info();
test_add_config();
@@ -70,19 +68,6 @@
@INC = (@a, @b, @c);
}
-# need to run from config phase, since it registers PerlPostConfigHandler
-sub register_post_config_startup {
- # most of the startup code needs to be run at the post_config
- # phase
- Apache->server->push_handlers(PerlPostConfigHandler => sub {
- my $pool = Apache->server->process->pool;
- my $t_conf_path = Apache::ServerUtil::server_root_relative($pool,
- "conf");
- require "$t_conf_path/post_config_startup.pl";
- return Apache::OK;
- });
-}
-
# this can be run from post_config_startup.pl, but then it'll do the
# logging twice, so in this case it's actually good to have this code
# run during config phase, so it's logged only once (even though it's
Index: t/response/TestVhost/config.pm
===================================================================
--- t/response/TestVhost/config.pm (revision 112024)
+++ t/response/TestVhost/config.pm (working copy)
@@ -17,19 +17,25 @@
use Apache::Const -compile => 'OK';
+our $Restart_Count;
+
# using a different from 'handler' name on purpose, to make sure
# that the module is preloaded at the server startup
sub my_handler {
my $r = shift;
- plan $r, tests => 1;
+ plan $r, tests => 2;
{
my $expected = $r->document_root;
my $received = $r->dir_config->get('DocumentRootCheck');
ok t_cmp(canonpath($received), canonpath($expected), "DocumentRoot");
}
-
+
+ {
+ ok t_cmp($Restart_Count, 2, "PerlPostConfigRequire");
+ }
+
Apache::OK;
}
@@ -56,6 +62,7 @@
# private to this vhost stuff
PerlRequire "@documentroot@/vhost/startup.pl"
+ PerlPostConfigRequire "@documentroot@/vhost/post_config.pl"
# <Location /TestVhost__config> container is added via add_config
# in t/htdocs/vhost/startup.pl
Index: Changes
===================================================================
--- Changes (revision 112024)
+++ Changes (working copy)
@@ -12,6 +12,14 @@
=item 1.99_19-dev
+New configuration directives: [Gozer]
+ - PerlConfigRequire
+ Just like PerlRequire, but _always_ triggers an immediate
+ interpreter startup
+ - PerlPostConfigRequire
+ A delayed form of PerlRequire, that waits until the post_config
+ phase before require'ing files
+
Ignore Apache-Test/META.yml in distribution tarballs until PAUSE
is capable of handling multiple META.yml files in one distro [Gozer]
signature.asc
Description: OpenPGP digital signature
