I've found that mod_perl can get confused when dealing with method
calls during a redirect_internal phase:

 1. page /1 uses method calls, and works when accessed as /1

 2. an other page /R uses internal_redirect to go to /1, and mod_perl
    fails with an undefined subroutine error.

This has been seen on:

  apache 1.3.9-14, perl 5.004.05-1.1, and mod_perl 1.25-3 (Debian "potato")

and on:

  apache 1.3.22-2.1, perl 5.6.1-6, and mod_perl 1.26-1 (Debian "woody"/testing)

How to reproduce:

Use this startup.pl file:

======================================================================
# Common
package Common;

use Apache::Constants qw(:common);

sub handler($$)
  {
    my $self = shift;
    my $req = shift;
    $req->content_type('text/plain');
    $req->send_http_header();
    $req->print($self->doit());
    return OK;
  }

sub doit
  {
    return "COMMON";
  }

# Common::Impl1
package Common::Impl1;

@ISA=qw(Common);

sub doit
  {
    return "IMPL1\n";
  }

# Common::Impl2;
package Common::Impl2;

@ISA=qw(Common);

sub doit
  {
    return "IMPL2\n";
  }

# Redir
package Redir;

use Apache::Constants qw(:common);

sub handler
  {
    my $req = shift;
    $req->internal_redirect("/1");
    return OK;
  }

1;
======================================================================

PerlRequire the above, and use the following apache configuration:

======================================================================
<Location /0>
  Order allow,deny
  Allow from all
  SetHandler perl-script
  PerlHandler Common
</Location>

<Location /1>
  Order allow,deny
  Allow from all
  SetHandler perl-script
  PerlHandler Common::Impl1
</Location>

<Location /2>
  Order allow,deny
  Allow from all
  SetHandler perl-script
  PerlHandler Common::Impl2
</Location>

<Location /R>
  Order allow,deny
  Allow from all
  SetHandler perl-script
  PerlHandler Redir
</Location>

PerlRequire startup.pl
======================================================================

Then, directing a web browser to /0 prints COMMON, to /1 prints IMPL1,
to /2 prints IMPL2, as expectected.

Similarly, when pointing to /R (which redirects internally to /1),
IMPL1 should appear.

However, I get a 500 Internal server error and this in the logs:

[error] Undefined subroutine &Common::Impl1::handler called at
startup.pl line 49.

I've tried to debug the problem, and the problem lies inside 
perl_handler_ismethod() in src/modules/perl/mod_perl.c: it returns
different values when called from inside the internal_redirect than
called without internal_redirect.

Inside perl_handler_ismethod():

    if(!sub) return 0;
    sv = newSVpv(sub,0);
    if(!(cv = sv_2cv(sv, &stash, &gv, FALSE))) {
        GV *gvp = gv_fetchmethod(pclass, sub);
        if (gvp) cv = GvCV(gvp);

sv_2cv() returns different values when called from inside an
internal_redirect than called without
internal_redirect. Unfortunately, I could not grok sv_2cv(). It's not
even documented in the perl docs.

Phil.

Reply via email to