dougm 01/03/09 15:46:38 Modified: lib/ModPerl Code.pm src/modules/perl mod_perl.c mod_perl.h modperl_callback.c modperl_callback.h modperl_config.c modperl_config.h modperl_filter.c modperl_interp.c modperl_types.h modperl_util.c modperl_util.h Log: remove use of Perl structures in modperl_handler_t, as they are not usable in a threaded environment. replace with pre-hashed mgv structures for fast lookup Revision Changes Path 1.42 +3 -3 modperl-2.0/lib/ModPerl/Code.pm Index: Code.pm =================================================================== RCS file: /home/cvs/modperl-2.0/lib/ModPerl/Code.pm,v retrieving revision 1.41 retrieving revision 1.42 diff -u -r1.41 -r1.42 --- Code.pm 2001/02/22 03:49:22 1.41 +++ Code.pm 2001/03/09 23:46:33 1.42 @@ -87,10 +87,10 @@ #XXX: allow disabling of PerDir hooks on a PerDir basis my @hook_flags = (map { canon_uc($_) } keys %hooks); my %flags = ( - Srv => [qw(NONE CLONE PARENT ENABLED), @hook_flags, 'UNSET'], + Srv => [qw(NONE CLONE PARENT ENABLED AUTOLOAD), @hook_flags, 'UNSET'], Dir => [qw(NONE SEND_HEADER SETUP_ENV UNSET)], Interp => [qw(NONE IN_USE PUTBACK CLONED BASE)], - Handler => [qw(NONE PARSED METHOD OBJECT ANON)], + Handler => [qw(NONE PARSED METHOD OBJECT ANON AUTOLOAD)], ); my %flags_lookup = map { $_,1 } qw(Srv Dir); @@ -453,7 +453,7 @@ ); my @c_src_names = qw(interp tipool log config options callback gtop - util filter); + util filter mgv pcw); my @g_c_names = map { "modperl_$_" } qw(hooks directives flags xsinit); my @c_names = ('mod_perl', (map "modperl_$_", @c_src_names)); sub c_files { [map { "$_.c" } @c_names, @g_c_names] } 1.29 +22 -0 modperl-2.0/src/modules/perl/mod_perl.c Index: mod_perl.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- mod_perl.c 2001/02/04 22:19:11 1.28 +++ mod_perl.c 2001/03/09 23:46:34 1.29 @@ -115,6 +115,24 @@ } } +#ifdef USE_ITHREADS +static void modperl_init_clones(server_rec *s, apr_pool_t *p) +{ + for (; s; s=s->next) { + MP_dSCFG(s); + if (scfg->mip->tipool->idle) { + MP_TRACE_i(MP_FUNC, "%s interp already cloned\n", + s->server_hostname); + } + else { + MP_TRACE_i(MP_FUNC, "cloning interp for %s\n", + s->server_hostname); + modperl_tipool_init(scfg->mip->tipool); + } + } +} +#endif + void modperl_hook_init(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { @@ -139,6 +157,10 @@ ap_add_version_component(pconf, MP_VERSION_STRING); ap_add_version_component(pconf, Perl_form(aTHX_ "Perl/v%vd", PL_patchlevel)); + modperl_mgv_hash_handlers(pconf, s); +#ifdef USE_ITHREADS + modperl_init_clones(s, pconf); +#endif } void modperl_register_hooks(apr_pool_t *p) 1.26 +2 -0 modperl-2.0/src/modules/perl/mod_perl.h Index: mod_perl.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.h,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- mod_perl.h 2001/01/21 23:19:03 1.25 +++ mod_perl.h 2001/03/09 23:46:34 1.26 @@ -23,6 +23,8 @@ #include "modperl_options.h" #include "modperl_directives.h" #include "modperl_filter.h" +#include "modperl_pcw.h" +#include "modperl_mgv.h" void modperl_init(server_rec *s, apr_pool_t *p); void modperl_hook_init(apr_pool_t *pconf, apr_pool_t *plog, 1.21 +55 -251 modperl-2.0/src/modules/perl/modperl_callback.c Index: modperl_callback.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_callback.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- modperl_callback.c 2001/03/04 18:41:33 1.20 +++ modperl_callback.c 2001/03/09 23:46:35 1.21 @@ -1,41 +1,23 @@ #include "mod_perl.h" -static void require_module(pTHX_ const char *pv) +modperl_handler_t *modperl_handler_new(apr_pool_t *p, const char *name) { - SV* sv; - dSP; - PUSHSTACKi(PERLSI_REQUIRE); - PUTBACK; - sv = sv_newmortal(); - sv_setpv(sv, "require "); - sv_catpv(sv, pv); - eval_sv(sv, G_DISCARD); - SPAGAIN; - POPSTACK; -} - -modperl_handler_t *modperl_handler_new(apr_pool_t *p, void *h, int type) -{ modperl_handler_t *handler = (modperl_handler_t *)apr_pcalloc(p, sizeof(*handler)); - - switch (type) { - case MP_HANDLER_TYPE_SV: - handler->cv = SvREFCNT_inc((SV*)h); - MpHandlerPARSED_On(handler); - break; - case MP_HANDLER_TYPE_CHAR: - handler->name = (char *)h; - MP_TRACE_h(MP_FUNC, "new handler %s\n", handler->name); - break; - }; - apr_pool_cleanup_register(p, (void*)handler, - modperl_handler_cleanup, apr_pool_cleanup_null); + handler->name = name; + MP_TRACE_h(MP_FUNC, "new handler %s\n", handler->name); return handler; } +modperl_handler_t *modperl_handler_dup(apr_pool_t *p, + modperl_handler_t *h) +{ + MP_TRACE_h(MP_FUNC, "dup handler %s\n", h->name); + return modperl_handler_new(p, h->name); +} + void modperl_handler_make_args(pTHX_ AV *av, ...) { va_list args; @@ -59,221 +41,31 @@ va_end(args); } - -apr_status_t modperl_handler_cleanup(void *data) -{ - modperl_handler_t *handler = (modperl_handler_t *)data; - modperl_handler_unparse(handler); - return APR_SUCCESS; -} - -void modperl_handler_cache_cv(pTHX_ modperl_handler_t *handler, CV *cv) -{ - if (1) { - /* XXX: figure out how to invalidate cache - * e.g. if subroutine is redefined - */ - handler->cv = SvREFCNT_inc((SV*)cv); - /* handler->cvgen = MP_sub_generation; */; - } - else { - handler->cv = Perl_newSVpvf(aTHX_ "%s::%s", - HvNAME(GvSTASH(CvGV(cv))), - GvNAME(CvGV(cv))); - } - MP_TRACE_h(MP_FUNC, "caching %s::%s\n", - HvNAME(GvSTASH(CvGV(cv))), - GvNAME(CvGV(cv))); -} - -int modperl_handler_lookup(pTHX_ modperl_handler_t *handler, - char *package, char *name) -{ - CV *cv; - GV *gv; - HV *stash = gv_stashpv(package, FALSE); - - if (!stash) { - MP_TRACE_h(MP_FUNC, "package %s not defined, attempting to load\n", - package); - require_module(aTHX_ package); - if (SvTRUE(ERRSV)) { - MP_TRACE_h(MP_FUNC, "failed to load %s package\n", package); - return 0; - } - else { - MP_TRACE_h(MP_FUNC, "loaded %s package\n", package); - if (!(stash = gv_stashpv(package, FALSE))) { - MP_TRACE_h(MP_FUNC, "%s package still does not exist\n", - package); - return 0; - } - } - } - - if ((gv = gv_fetchmethod(stash, name)) && (cv = GvCV(gv))) { - if (CvFLAGS(cv) & CVf_METHOD) { /* sub foo : method {}; */ - MpHandlerMETHOD_On(handler); - handler->obj = newSVpv(package, 0); - handler->cv = newSVpv(name, 0); - } - else { - modperl_handler_cache_cv(aTHX_ handler, cv); - } - - MpHandlerPARSED_On(handler); - MP_TRACE_h(MP_FUNC, "found `%s' in class `%s' as a %s\n", - name, HvNAME(stash), - MpHandlerMETHOD(handler) ? "method" : "function"); - - return 1; - } - - MP_TRACE_h(MP_FUNC, "`%s' not found in class `%s'\n", - name, HvNAME(stash)); - - return 0; -} - -void modperl_handler_unparse(modperl_handler_t *handler) -{ - dTHXa(handler->perl); - int was_parsed = handler->args || handler->cv || handler->obj; - - if (!MpHandlerPARSED(handler)) { - if (was_parsed) { - MP_TRACE_h(MP_FUNC, "handler %s was parsed, but not flagged\n", - handler->name); - } - else { - MP_TRACE_h(MP_FUNC, "handler %s was never parsed\n", handler->name); - return; - } - } - - MpHandlerFLAGS(handler) = 0; - handler->cvgen = 0; - -#if 0 - if (handler->args) { - av_clear(handler->args); - SvREFCNT_dec((SV*)handler->args); - handler->args = Nullav; - } -#endif - if (handler->cv) { - SvREFCNT_dec(handler->cv); - handler->cv = Nullsv; - } - if (handler->obj) { - SvREFCNT_dec(handler->obj); - handler->obj = Nullsv; - } - - MP_TRACE_h(MP_FUNC, "%s unparsed\n", handler->name); -} -int modperl_handler_parse(pTHX_ modperl_handler_t *handler) +int modperl_callback(pTHX_ modperl_handler_t *handler, apr_pool_t *p, + AV *args) { - char *name = handler->name; - char *tmp; - CV *cv; - -#ifdef USE_ITHREADS - handler->perl = aTHX; -#endif - - if (strnEQ(name, "sub ", 4)) { - handler->cv = eval_pv(name, FALSE); - MP_TRACE_h(MP_FUNC, "handler is anonymous\n"); - if (!SvTRUE(handler->cv) || SvTRUE(ERRSV)) { - MP_TRACE_h(MP_FUNC, "eval failed: %s\n", SvPVX(ERRSV)); - handler->cv = Nullsv; - return 0; - } - SvREFCNT_inc(handler->cv); - MpHandlerANON_On(handler); - MpHandlerPARSED_On(handler); - return 1; - } - - if ((tmp = strstr(name, "->"))) { - char package[256]; /*XXX*/ - int package_len = strlen(name) - strlen(tmp); - apr_cpystrn(package, name, package_len+1); - - MpHandlerMETHOD_On(handler); - handler->cv = newSVpv(&tmp[2], 0); - - if (*package == '$') { - SV *obj = eval_pv(package, FALSE); - - if (SvTRUE(obj)) { - handler->obj = SvREFCNT_inc(obj); - if (SvROK(obj) && sv_isobject(obj)) { - MpHandlerOBJECT_On(handler); - MP_TRACE_h(MP_FUNC, "handler object %s isa %s\n", - package, HvNAME(SvSTASH((SV*)SvRV(obj)))); - } - else { - MP_TRACE_h(MP_FUNC, "%s is not an object, pv=%s\n", - package, SvPV_nolen(obj)); - } - } - else { - MP_TRACE_h(MP_FUNC, "failed to thaw %s\n", package); - return 0; - } - } - - if (!handler->obj) { - handler->obj = newSVpv(package, package_len); - MP_TRACE_h(MP_FUNC, "handler method %s isa %s\n", - SvPVX(handler->cv), package); - } - - MpHandlerPARSED_On(handler); - return 1; - } - - if ((cv = get_cv(name, FALSE))) { - modperl_handler_cache_cv(aTHX_ handler, cv); - MpHandlerPARSED_On(handler); - return 1; - } - - if (modperl_handler_lookup(aTHX_ handler, name, "handler")) { - return 1; - } - - return 0; -} - -int modperl_callback(pTHX_ modperl_handler_t *handler, apr_pool_t *p) -{ + CV *cv=Nullcv; + I32 flags = G_EVAL|G_SCALAR; dSP; int count, status; #ifdef USE_ITHREADS - if (p) { - /* under ithreads, each handler needs to get_cv() from the - * selected interpreter so the proper CvPADLIST is used - * XXX: this should probably be reworked so threads can cache - * parsed handlers + if (p && !MpHandlerPARSED(handler)) { + /* + * cannot update the handler structure at request time without + * locking, so just copy it */ - modperl_handler_t *new_handler = - modperl_handler_new(p, (void*)handler->name, - MP_HANDLER_TYPE_CHAR); - - new_handler->args = handler->args; - handler->args = Nullav; - handler = new_handler; + handler = modperl_handler_dup(p, handler); } #endif + MP_TRACE_h_do(MpHandler_dump_flags(handler, handler->name)); + if (!MpHandlerPARSED(handler)) { - if (!modperl_handler_parse(aTHX_ handler)) { - MP_TRACE_h(MP_FUNC, "failed to parse handler `%s'\n", + MpHandlerAUTOLOAD_On(handler); + if (!modperl_mgv_resolve(aTHX_ handler, p, handler->name)) { + MP_TRACE_h(MP_FUNC, "failed to resolve handler `%s'\n", handler->name); return HTTP_INTERNAL_SERVER_ERROR; } @@ -283,26 +75,41 @@ PUSHMARK(SP); if (MpHandlerMETHOD(handler)) { - XPUSHs(handler->obj); + GV *gv = modperl_mgv_lookup(aTHX_ handler->mgv_obj); + XPUSHs(modperl_mgv_sv(gv)); } - if (handler->args) { - I32 items = AvFILLp(handler->args) + 1; + if (args) { + I32 items = AvFILLp(args) + 1; EXTEND(SP, items); - Copy(AvARRAY(handler->args), SP + 1, items, SV*); + Copy(AvARRAY(args), SP + 1, items, SV*); SP += items; } PUTBACK; - if (MpHandlerMETHOD(handler)) { - count = call_method(SvPVX(handler->cv), G_EVAL|G_SCALAR); + if (MpHandlerANON(handler)) { + SV *sv = eval_pv(handler->name, TRUE); /* XXX: cache */ + cv = (CV*)SvRV(sv); } else { - count = call_sv(handler->cv, G_EVAL|G_SCALAR); + GV *gv = modperl_mgv_lookup(aTHX_ handler->mgv_cv); + if (gv) { + cv = modperl_mgv_cv(gv); + } + else { + char *name = modperl_mgv_as_string(aTHX_ handler->mgv_cv, p); + MP_TRACE_h(MP_FUNC, "lookup of %s failed\n", name); + } } + if (MpHandlerMETHOD(handler)) { + flags |= G_METHOD; + } + + count = call_sv((SV*)cv, flags); + SPAGAIN; if (count != 1) { @@ -316,7 +123,7 @@ FREETMPS;LEAVE; if (SvTRUE(ERRSV)) { - MP_TRACE_h(MP_FUNC, "$@ = %s\n", SvPVX(ERRSV)); + MP_TRACE_h(MP_FUNC, "$@ = %s", SvPVX(ERRSV)); status = HTTP_INTERNAL_SERVER_ERROR; } @@ -422,30 +229,27 @@ break; case MP_HANDLER_TYPE_PROC: { - apr_pool_t *p; + apr_pool_t *pconf; va_start(args, type); - p = va_arg(args, apr_pool_t *); + pconf = va_arg(args, apr_pool_t *); va_end(args); + if (!p) { + p = pconf; + } + modperl_handler_make_args(aTHX_ av_args, - "Apache::Pool", p, + "Apache::Pool", pconf, "Apache::Server", s, NULL); } break; }; for (i=0; i<av->nelts; i++) { -#ifdef USE_ITHREADS - if (!handlers[i]->perl) { - handlers[i]->perl = aTHX; - } -#endif - handlers[i]->args = av_args; - if ((status = modperl_callback(aTHX_ handlers[i], p)) != OK) { + if ((status = modperl_callback(aTHX_ handlers[i], p, av_args)) != OK) { status = modperl_errsv(aTHX_ status, r, s); } - handlers[i]->args = Nullav; MP_TRACE_h(MP_FUNC, "%s returned %d\n", handlers[i]->name, status); 1.11 +6 -13 modperl-2.0/src/modules/perl/modperl_callback.h Index: modperl_callback.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_callback.h,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- modperl_callback.h 2001/02/18 21:55:08 1.10 +++ modperl_callback.h 2001/03/09 23:46:35 1.11 @@ -16,22 +16,15 @@ #define MP_HANDLER_TYPE_PROC 4 #define MP_HANDLER_TYPE_FILE 5 -modperl_handler_t *modperl_handler_new(apr_pool_t *p, void *h, int type); +modperl_handler_t *modperl_handler_new(apr_pool_t *p, const char *name); -void modperl_handler_make_args(pTHX_ AV *avp, ...); - -apr_status_t modperl_handler_cleanup(void *data); - -void modperl_handler_cache_cv(pTHX_ modperl_handler_t *handler, CV *cv); +modperl_handler_t *modperl_handler_dup(apr_pool_t *p, + modperl_handler_t *h); -int modperl_handler_lookup(pTHX_ modperl_handler_t *handler, - char *package, char *name); - -void modperl_handler_unparse(modperl_handler_t *handler); - -int modperl_handler_parse(pTHX_ modperl_handler_t *handler); +void modperl_handler_make_args(pTHX_ AV *avp, ...); -int modperl_callback(pTHX_ modperl_handler_t *handler, apr_pool_t *p); +int modperl_callback(pTHX_ modperl_handler_t *handler, apr_pool_t *p, + AV *args); int modperl_run_handlers(int idx, request_rec *r, conn_rec *c, server_rec *s, int type, ...); 1.18 +2 -2 modperl-2.0/src/modules/perl/modperl_config.c Index: modperl_config.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_config.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- modperl_config.c 2001/02/08 19:42:05 1.17 +++ modperl_config.c 2001/03/09 23:46:35 1.18 @@ -3,8 +3,8 @@ char *modperl_cmd_push_handlers(MpAV **handlers, const char *name, apr_pool_t *p) { - modperl_handler_t *h = modperl_handler_new(p, (void*)name, - MP_HANDLER_TYPE_CHAR); + modperl_handler_t *h = modperl_handler_new(p, name); + if (!*handlers) { *handlers = apr_array_make(p, 1, sizeof(modperl_handler_t *)); MP_TRACE_d(MP_FUNC, "created handler stack\n"); 1.17 +6 -0 modperl-2.0/src/modules/perl/modperl_config.h Index: modperl_config.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_config.h,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- modperl_config.h 2001/01/21 21:04:52 1.16 +++ modperl_config.h 2001/03/09 23:46:35 1.17 @@ -70,4 +70,10 @@ #define MP_dSCFG(s) \ modperl_srv_config_t *scfg = modperl_srv_config_get(s) +#ifdef USE_ITHREADS +# define MP_dSCFG_dTHX dTHXa(scfg->mip->parent->perl) +#else +# define MP_dSCFG_dTHX dTHXa(scfg->perl) +#endif + #endif /* MODPERL_CONFIG_H */ 1.5 +6 -7 modperl-2.0/src/modules/perl/modperl_filter.c Index: modperl_filter.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_filter.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- modperl_filter.c 2001/02/08 19:42:08 1.4 +++ modperl_filter.c 2001/03/09 23:46:35 1.5 @@ -81,6 +81,7 @@ int modperl_run_filter(modperl_filter_t *filter) { + AV *args; int status; modperl_handler_t *handler = ((modperl_filter_ctx_t *)filter->f->ctx)->handler; @@ -94,25 +95,23 @@ pTHX; modperl_interp_t *interp = NULL; interp = modperl_interp_select(r, c, s); - handler->perl = aTHX = interp->perl; + aTHX = interp->perl; PERL_SET_CONTEXT(aTHX); #endif - handler->args = newAV(); + args = newAV(); - modperl_handler_make_args(aTHX_ handler->args, + modperl_handler_make_args(aTHX_ args, filter_classes[filter->mode], filter, NULL); - if ((status = modperl_callback(aTHX_ handler, p)) != OK) { + if ((status = modperl_callback(aTHX_ handler, p, args)) != OK) { status = modperl_errsv(aTHX_ status, r, s); } - SvREFCNT_dec((SV*)handler->args); - handler->args = Nullav; + SvREFCNT_dec((SV*)args); MP_TRACE_f(MP_FUNC, "%s returned %d\n", handler->name, status); - return status; } 1.18 +2 -1 modperl-2.0/src/modules/perl/modperl_interp.c Index: modperl_interp.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_interp.c,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- modperl_interp.c 2001/02/08 19:42:13 1.17 +++ modperl_interp.c 2001/03/09 23:46:35 1.18 @@ -173,7 +173,8 @@ mip->parent = modperl_interp_new(p, mip, NULL); aTHX = mip->parent->perl = perl; - modperl_tipool_init(tipool); + /* this happens post-config in mod_perl.c:modperl_init_clones() */ + /* modperl_tipool_init(tipool); */ apr_pool_cleanup_register(p, (void*)mip, modperl_interp_pool_destroy, 1.22 +15 -9 modperl-2.0/src/modules/perl/modperl_types.h Index: modperl_types.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_types.h,v retrieving revision 1.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- modperl_types.h 2001/02/28 05:46:53 1.21 +++ modperl_types.h 2001/03/09 23:46:36 1.22 @@ -37,7 +37,7 @@ modperl_interp_pool_t *mip; PerlInterpreter *perl; int num_requests; - int flags; + U8 flags; #ifdef MP_TRACE unsigned long tid; #endif @@ -136,17 +136,23 @@ MpAV *handlers[MP_PER_DIR_NUM_HANDLERS]; MpHV *SetEnv; MpHV *SetVars; - int flags; + U8 flags; } modperl_dir_config_t; +typedef struct modperl_mgv_t modperl_mgv_t; + +struct modperl_mgv_t { + char *name; + int len; + UV hash; + modperl_mgv_t *next; +}; + typedef struct { - SV *obj; /* object or classname if cv is a method */ - SV *cv; /* subroutine reference or name */ - char *name; /* orignal name from .conf if any */ - int cvgen; /* XXX: for caching */ - AV *args; /* XXX: switch to something lighter */ - int flags; - PerlInterpreter *perl; + modperl_mgv_t *mgv_obj; + modperl_mgv_t *mgv_cv; + const char *name; /* orignal name from .conf if any */ + U8 flags; } modperl_handler_t; #define MP_HANDLER_TYPE_CHAR 1 1.3 +17 -0 modperl-2.0/src/modules/perl/modperl_util.c Index: modperl_util.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_util.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- modperl_util.c 2001/01/02 06:40:20 1.2 +++ modperl_util.c 2001/03/09 23:46:36 1.3 @@ -1,5 +1,22 @@ #include "mod_perl.h" +int modperl_require_module(pTHX_ const char *pv) +{ + SV *sv; + + dSP; + PUSHSTACKi(PERLSI_REQUIRE); + PUTBACK; + sv = sv_newmortal(); + sv_setpv(sv, "require "); + sv_catpv(sv, pv); + eval_sv(sv, G_DISCARD); + SPAGAIN; + POPSTACK; + + return SvTRUE(ERRSV) ? FALSE : TRUE; +} + MP_INLINE request_rec *modperl_sv2request_rec(pTHX_ SV *sv) { request_rec *r = NULL; 1.4 +2 -0 modperl-2.0/src/modules/perl/modperl_util.h Index: modperl_util.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_util.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- modperl_util.h 2001/02/28 05:25:00 1.3 +++ modperl_util.h 2001/03/09 23:46:36 1.4 @@ -18,4 +18,6 @@ int modperl_errsv(pTHX_ int status, request_rec *r, server_rec *s); +int modperl_require_module(pTHX_ const char *pv); + #endif /* MODPERL_UTIL_H */