Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Hiding" $ENV{MOD_PERL} deletes it for all mod_perl code - also non-Plack/PSGI apps #562

Open
pmorch opened this issue Sep 5, 2016 · 2 comments

Comments

@pmorch
Copy link

pmorch commented Sep 5, 2016

$ENV{MOD_PERL} under mod_perl does not behave like a normal %ENV variable does in normal perl. Any attempt to modify it that I've tried, even with delete local, leaves it undef for any later requests, Plack/PSGI or not.

So far, I have not found a way to run "normal" mod_perl code that depends on checking $ENV{MOD_PERL} after any PerlResponseHandler Plack::Handler::Apache2 request has been handled. So in effect, this issue in Plack::Handler::Apache2 bug turns mod_perl into Plack/PSGI only :-(

The problematic code is:

sub load_app {
    my($class, $app) = @_;
    return $apps{$app} ||= do {
        # Trick Catalyst, CGI.pm, CGI::Cookie and others that check
        # for $ENV{MOD_PERL}.
        #
        # Note that we delete it instead of just localizing
        # $ENV{MOD_PERL} because some users may check if the key
        # exists, and we do it this way because "delete local" is new
        # in 5.12:
        # http://perldoc.perl.org/5.12.0/perldelta.html#delete-local
        local $ENV{MOD_PERL};
        delete $ENV{MOD_PERL};

        Plack::Util::load_psgi $app;
    };
}

The delete local should work, and does work in a standalone perl process. But not under mod_perl, apparently. I've tried printf STDERR "MOD_PERL: %s\n", $ENV{MOD_PERL} // 'undef'; in the beginning of Plack::Handler::Apache2::handler() and it prints the mod_perl version for the first request but undef for the second request. (Run with apache2ctl -X and look for output in /var/log/apache2/error.log.)

To illustrate, here is the simplest test case I could come up with:

Alias /perl/ /home/peter/registry/
<Location /perl/>
    SetHandler perl-script
    PerlResponseHandler ModPerl::Registry
    PerlOptions +ParseHeaders
    Require all granted
    Options +ExecCGI
</Location>

and then in /home/peter/registry/env.pl:

#!/usr/bin/perl
print "Content-type: text/plain\n\n";
print '$ENV{MOD_PERL}: ', $ENV{MOD_PERL} // 'undef', "\n";
{
    local $ENV{MOD_PERL};
    delete $ENV{MOD_PERL};
};

The first time it prints:

$ENV{MOD_PERL}: mod_perl/2.0.9dev

But the second time it prints

$ENV{MOD_PERL}: undef

Yeah, I get it. It isn't supposed to do that. But it does.

I find this very serious, because we're mixing PerlResponseHandler Plack::Handler::Apache2 for some paths, and PerlResponseHandler ModPerl::Registry for many, many other paths. But $ENV{MOD_PERL} is undef for all the PerlResponseHandler ModPerl::Registry paths because of this.

A workaround is to create a PerlResponseHandler derived from Plack::Handler::Apache2:

package OurMojo::Apache2Handler;
use strict;

=head1 Work around bug in C<Plack::Handler::Apache2>

C<Plack::Handler::Apache2> messes with C<$ENV{MOD_PERL}> and that makes it
undef for everybody else. This handler uses as much of
C<Plack::Handler::Apache2> as possible but leaves C<$ENV{MOD_PERL}> alone.

=cut

use parent 'Plack::Handler::Apache2';

my %apps; # psgi file to $app mapping

sub load_app {
    my($class, $app) = @_;
    return $apps{$app} ||= do {
        Plack::Util::load_psgi $app;
    };
}

sub handler {
    my $class = __PACKAGE__;
    my $r     = shift;
    my $psgi  = $r->dir_config('psgi_app');
    $class->call_app($r, $class->load_app($psgi));
}

1;

Versions: Debian stable. apache2 2.4.10-10+deb8u4, libapache2-mod-perl2 2.0.9~1624218-2+deb8u1, perl 5.20.2-3+deb8u3, libplack-perl 1.0033-1. For Plack::Handler::Apache2, I've also tried today's git master HEAD.

@negachov
Copy link

@pmorch
Copy link
Author

pmorch commented Jan 14, 2020

Thanks, @negachov, that looks very promising. Because of this (and to get Websocket support) we went with a standalone Mojolicious process instead, so I don't have the original setup any longer. This issue does look very similar to https://rt.cpan.org/Public/Bug/Display.html?id=98750 to me, and I'm fine with closing this issue since it apparently really is a mod_perl bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants