stas        2004/01/22 13:55:50

  Modified:    src/modules/perl modperl_cmd.c
               .        Changes
  Added:       t/htdocs/vhost startup.pl
               t/vhost  config.t
               t/response/TestVhost config.pm
  Log:
  fix context problems in <perl> sections and
  PerlModule/PerlLoadModule/PerlRequre under threaded mpms w/
  PerlOptions +Parent/+Clone in Vhosts + TestVhost::config test.
  
  Revision  Changes    Path
  1.53      +65 -24    modperl-2.0/src/modules/perl/modperl_cmd.c
  
  Index: modperl_cmd.c
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_cmd.c,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -u -u -r1.52 -r1.53
  --- modperl_cmd.c     19 Dec 2003 01:17:31 -0000      1.52
  +++ modperl_cmd.c     22 Jan 2004 21:55:49 -0000      1.53
  @@ -1,5 +1,41 @@
   #include "mod_perl.h"
   
  +#ifdef USE_ITHREADS
  +
  +/*
  + * perl context overriding and restoration is required when
  + * PerlOptions +Parent/+Clone is used in vhosts, and perl is used to
  + * at the server startup. So that <Perl> sections, PerlLoadModule,
  + * PerlModule and PerlRequire are all run using the right perl context
  + * and restore to the original context when they are done.
  + *
  + * As of perl-5.8.3 it's unfortunate that it uses PERL_GET_CONTEXT and
  + * doesn't rely on the passed pTHX internally. When and if perl is
  + * fixed to always use pTHX if available, this context switching mess
  + * can be removed.
  + */
  +
  +#define MP_PERL_DECLARE_CONTEXT \
  +    PerlInterpreter *orig_perl; \
  +    pTHX;
  +
  +/* XXX: .htaccess support cannot use this perl with threaded MPMs */
  +#define MP_PERL_OVERRIDE_CONTEXT    \
  +    orig_perl = PERL_GET_CONTEXT;   \
  +    aTHX = scfg->mip->parent->perl; \
  +    PERL_SET_CONTEXT(aTHX);
  +
  +#define MP_PERL_RESTORE_CONTEXT     \
  +    PERL_SET_CONTEXT(orig_perl);
  +
  +#else
  +
  +#define MP_PERL_DECLARE_CONTEXT
  +#define MP_PERL_OVERRIDE_CONTEXT
  +#define MP_PERL_RESTORE_CONTEXT
  +
  +#endif
  +
   static char *modperl_cmd_unclosed_directive(cmd_parms *parms)
   {
       return apr_pstrcat(parms->pool, parms->cmd->name,
  @@ -105,6 +141,7 @@
   MP_CMD_SRV_DECLARE(modules)
   {
       MP_dSCFG(parms->server);
  +    MP_PERL_DECLARE_CONTEXT;
   
       if (modperl_is_running() &&
           modperl_init_vhost(parms->server, parms->pool, NULL) != OK)
  @@ -113,27 +150,29 @@
       }
   
       if (modperl_is_running()) {
  -#ifdef USE_ITHREADS
  -        /* XXX: .htaccess support cannot use this perl with threaded MPMs */
  -        dTHXa(scfg->mip->parent->perl);
  -#endif
  -        MP_TRACE_d(MP_FUNC, "load PerlModule %s\n", arg);
  +        char *error = NULL;
   
  +        MP_TRACE_d(MP_FUNC, "load PerlModule %s\n", arg);
  +        
  +        MP_PERL_OVERRIDE_CONTEXT;
           if (!modperl_require_module(aTHX_ arg, FALSE)) {
  -            return SvPVX(ERRSV);
  +            error = SvPVX(ERRSV);
           }
  +        MP_PERL_RESTORE_CONTEXT;
  +
  +        return error;
       }
       else {
           MP_TRACE_d(MP_FUNC, "push PerlModule %s\n", arg);
           *(const char **)apr_array_push(scfg->PerlModule) = arg;
  +        return NULL;
       }
  -
  -    return NULL;
   }
   
   MP_CMD_SRV_DECLARE(requires)
   {
       MP_dSCFG(parms->server);
  +    MP_PERL_DECLARE_CONTEXT;
   
       if (modperl_is_running() &&
           modperl_init_vhost(parms->server, parms->pool, NULL) != OK)
  @@ -142,23 +181,23 @@
       }
   
       if (modperl_is_running()) {
  -#ifdef USE_ITHREADS
  -        /* XXX: .htaccess support cannot use this perl with threaded MPMs */
  -        dTHXa(scfg->mip->parent->perl);
  -#endif
  +        char *error = NULL;
   
           MP_TRACE_d(MP_FUNC, "load PerlRequire %s\n", arg);
   
  +        MP_PERL_OVERRIDE_CONTEXT;
           if (!modperl_require_file(aTHX_ arg, FALSE)) {
  -            return SvPVX(ERRSV);
  +            error = SvPVX(ERRSV);
           }
  +        MP_PERL_RESTORE_CONTEXT;
  +
  +        return error;
       }
       else {
           MP_TRACE_d(MP_FUNC, "push PerlRequire %s\n", arg);
           *(const char **)apr_array_push(scfg->PerlRequire) = arg;
  +        return NULL;
       }
  -
  -    return NULL;
   }
   
   static MP_CMD_SRV_DECLARE2(handle_vars)
  @@ -332,7 +371,7 @@
           /*XXX: Less than optimal */
           code = apr_pstrcat(p, code, line, "\n", NULL);
       }
  -    
  +
       /* Here, we have to replace our current config node for the next pass */
       if (!*current) {
           *current = apr_pcalloc(p, sizeof(**current));
  @@ -372,7 +411,7 @@
       int dollar_zero_tainted;
   #ifdef USE_ITHREADS
       MP_dSCFG(s);
  -    pTHX;
  +    MP_PERL_DECLARE_CONTEXT;
   #endif
   
       if (!(arg && *arg)) {
  @@ -386,10 +425,7 @@
           return "init mod_perl vhost failed";
       }
       
  -#ifdef USE_ITHREADS
  -    /* XXX: .htaccess support cannot use this perl with threaded MPMs */
  -    aTHX = scfg->mip->parent->perl;
  -#endif
  +    MP_PERL_OVERRIDE_CONTEXT;
   
       /* data will be set by a <Perl> section */
       if ((options = parms->directive->data)) {
  @@ -443,7 +479,9 @@
       if (SvTRUE(ERRSV)) {
           SV *strict;
           if ((strict = MP_STRICT_PERLSECTIONS_SV) && SvTRUE(strict)) {
  -            return SvPVX(ERRSV);
  +            char *error = SvPVX(ERRSV);
  +            MP_PERL_RESTORE_CONTEXT;
  +            return error;
           }
           else {
               modperl_log_warn(s, apr_psprintf(p, "Syntax error at %s:%d %s", 
  @@ -473,12 +511,15 @@
           }
           
           if (status != OK) {
  -            return SvTRUE(ERRSV) ? SvPVX(ERRSV) :
  +            char *error = SvTRUE(ERRSV) ? SvPVX(ERRSV) :
                   apr_psprintf(p, "<Perl> handler %s failed with status=%d",
                                handler->name, status);
  +            MP_PERL_RESTORE_CONTEXT;
  +            return error;
           }
       }
   
  +    MP_PERL_RESTORE_CONTEXT;
       return NULL;
   }
   
  @@ -515,7 +556,7 @@
       char line[MAX_STRING_LEN];
   
       while (!ap_cfg_getline(line, sizeof(line), parms->config_file)) {
  -     /* soak up rest of the file */
  +        /* soak up rest of the file */
       }
   
       return NULL;
  
  
  
  1.1                  modperl-2.0/t/htdocs/vhost/startup.pl
  
  Index: startup.pl
  ===================================================================
  use warnings;
  use strict;
  
  use Apache2;
  use Apache::ServerUtil ();
  use Apache::Server ();
  
  use File::Spec::Functions qw(catdir);
  
  # base server
  # XXX: at the moment this is wrong, since it return the base server $s and not the 
vhost's one. needs to be fixed.
  my $s = Apache->server;
  
  my $vhost_doc_root = catdir Apache::Server::server_root, qw(htdocs vhost);
  
  # testing $s->add_config() in vhost
  my $conf = <<"EOC";
  # must use PerlModule here to check for segfaults
  # and that the module is loaded by vhost
  PerlModule TestVhost::config
  PerlSetVar DocumentRootCheck $vhost_doc_root
  <Location /TestVhost__config>
      SetHandler modperl
      PerlResponseHandler TestVhost::config::my_handler
  </Location>
  EOC
  
  $s->add_config([split /\n/, $conf]);
  
  # this used to have problems on win32
  $s->add_config(['<Perl >', '1;', '</Perl>']);
  
  1;
  
  
  
  1.1                  modperl-2.0/t/vhost/config.t
  
  Index: config.t
  ===================================================================
  # the handler is configured in modperl_extra.pl via
  # Apache->server->add_config
  
  use Apache::TestUtil;
  use Apache::TestRequest 'GET';
  
  my $config = Apache::Test::config();
  my $vars = $config->{vars};
  
  my $module = 'TestVhost::config';
  my $path = Apache::TestRequest::module2path($module);
  
  Apache::TestRequest::module($module);
  my $hostport = Apache::TestRequest::hostport($config);
  
  t_debug("connecting to $hostport");
  my $res = GET "http://$hostport/$path";;
  
  if ($res->is_success) {
      print $res->content;
  }
  else {
      if ($res->code == 404) {
          my $documentroot = $vars->{documentroot};
          die "this test gets its <Location> configuration added via " .
              "$documentroot/vhost/startup.pl, this could be the cause " .
              "of the failure";
      }
      else {
          die "server side has failed (response code: ", $res->code, "),\n",
              "see t/logs/error_log for more details\n";
      }
  }
  
  
  
  1.1                  modperl-2.0/t/response/TestVhost/config.pm
  
  Index: config.pm
  ===================================================================
  package TestVhost::config;
  
  # Test whether under threaded mpms (and not) a vhost with 'PerlOptions
  # +Parent', can run <Perl> sections, which call into config again via
  # add_config().
  
  use strict;
  use warnings FATAL => 'all';
  
  use Apache::Test;
  use Apache::TestUtil;
  
  use Apache::RequestUtil ();
  use APR::Table ();
  
  use File::Spec::Functions qw(catdir);
  
  use Apache::Const -compile => 'OK';
  
  # 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;
  
      {
          my $expected = $r->document_root;
          my $received = $r->dir_config->get('DocumentRootCheck');
          ok t_cmp($expected, $received, "DocumentRoot");
      }
  
      Apache::OK;
  }
  
  1;
  __END__
  <NoAutoConfig>
  <VirtualHost TestVhost::config>
      DocumentRoot @documentroot@/vhost
  
      <IfDefine PERL_USEITHREADS>
          # a new interpreter pool
          PerlOptions +Parent
      </IfDefine>
  
      # use test system's @INC
      PerlSwitches [EMAIL PROTECTED]@
  
      # mp2 modules
      PerlRequire "@serverroot@/conf/modperl_inc.pl"
  
      # private to this vhost stuff
      PerlRequire "@documentroot@/vhost/startup.pl"
  
      # <Location /TestVhost__config> container is added via add_config
      # in t/htdocs/vhost/startup.pl
  </VirtualHost>
  </NoAutoConfig>
  
  
  
  1.307     +4 -0      modperl-2.0/Changes
  
  Index: Changes
  ===================================================================
  RCS file: /home/cvs/modperl-2.0/Changes,v
  retrieving revision 1.306
  retrieving revision 1.307
  diff -u -u -r1.306 -r1.307
  --- Changes   19 Jan 2004 20:00:17 -0000      1.306
  +++ Changes   22 Jan 2004 21:55:50 -0000      1.307
  @@ -12,6 +12,10 @@
   
   =item 1.99_13-dev
   
  +fix context problems in <perl> sections and
  +PerlModule/PerlLoadModule/PerlRequre under threaded mpms w/
  +PerlOptions +Parent/+Clone in Vhosts + TestVhost::config test. [Stas]
  +
   moved many functions out of the Apache:: namespace:
     Apache::unescape_url()          is now Apache::URI::unescape_url()
     Apache::log_pid()               is now Apache::Log::log_pid()
  
  
  

Reply via email to