Stas Bekman wrote:
[...]
PerlRequire stays where it is.
PerlConfigFile = StartPerl + PerlRequire (ensures to be run at config phase)
Same as PerlLoadModule vs. PerlModule.
After some talk about exactly what to call these directive, here is a patch. It's late, so it doesn't include
docs or tests, but it should give a good idea of what's required to get this working.
PerlConfigRequire is basically just PerlRequire with an immediate perl startup
PerlPostConfigRequire delays requiring the files up to the last possible moment, before interpreters begin
to get cloned, at the begining of mp's post_config phase.
Feedback most welcome!
--------------------------------------------------------------------------------
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 111578)
+++ 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 111578)
+++ src/modules/perl/modperl_config.c (working copy)
@@ -155,6 +155,7 @@
scfg->PerlModule = apr_array_make(p, 2, sizeof(char *));
scfg->PerlRequire = apr_array_make(p, 2, sizeof(char *));
+ scfg->PerlPostConfigRequire = apr_array_make(p, 2, sizeof(char *));
scfg->argv = apr_array_make(p, 2, sizeof(char *));
@@ -437,6 +438,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 111578)
+++ src/modules/perl/modperl_types.h (working copy)
@@ -65,6 +65,11 @@
};
typedef struct {
+ const char *file;
+ PerlInterpreter *perl;
+} modperl_require_file_t;
+
+typedef struct {
/* s == startup grow
* r == runtime grow
*/
@@ -130,7 +135,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 111578)
+++ 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 111578)
+++ src/modules/perl/modperl_cmd.c (working copy)
@@ -266,6 +266,52 @@
}
}
+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;
+ modperl_require_file_t *require;
+
+ MP_CMD_SRV_CHECK;
+
+ if (APR_SUCCESS == apr_stat(&finfo, arg, APR_FINFO_TYPE, p)) {
+ if (finfo.filetype != APR_NOFILE) {
+ require = apr_pcalloc(p, sizeof(*require));
+
+ if (modperl_is_running()) {
+ MP_PERL_OVERRIDE_CONTEXT;
+ require->perl = aTHX;
+ MP_PERL_RESTORE_CONTEXT;
+ }
+
+ require->file = arg;
+
+ MP_TRACE_d(MP_FUNC, "push PerlPostConfigRequire %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 111578)
+++ 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/conf/modperl_extra.pl
===================================================================
--- t/conf/modperl_extra.pl (revision 111578)
+++ 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/conf/post_config_startup.pl
===================================================================
--- t/conf/post_config_startup.pl (revision 111578)
+++ t/conf/post_config_startup.pl (working copy)
@@ -148,3 +148,5 @@
}
1;
+
+die "blargh";
Index: t/conf/extra.conf.in
===================================================================
--- t/conf/extra.conf.in (revision 111578)
+++ t/conf/extra.conf.in (working copy)
@@ -1,6 +1,8 @@
# needed to test $r->psignature
ServerSignature On
+PerlPostConfigRequire @ServerRoot@/conf/post_config_startup.pl
+
# The following tests require more than one interpreter during the
# same request:
#
Index: todo/release
===================================================================
--- todo/release (revision 111578)
+++ todo/release (working copy)
@@ -4,15 +4,6 @@
-- see also todo/api_status
-* on restart DSO/static Perl loses STDERR: i.e. this code added to
- startup.pl:
-
- my $cnt = Apache::ServerUtil::restart_count();
- print STDERR "************* $cnt: AAAAAAAAAA *********\n";
-
- prints 1 but not 2.
- owner: gozer
-
* pools that go out of scope:
perl -MApache2 -MAPR::Pool -MAPR::PerlIO -le ';
Index: Changes
===================================================================
--- Changes (revision 111578)
+++ Changes (working copy)
@@ -12,6 +12,14 @@
=item 1.99_18-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
+
new function ModPerl::Util::current_perl_id() which returns something
like (.e.g 0x92ac760) (aTHX) under threaded mpm and 0 under
non-threaded perl (0x0). Useful for debugging modperl under threaded
signature.asc
Description: OpenPGP digital signature
