perl-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Steve Hay <>
Subject Re: mod_perl head build with httpd 2.4.6 on Linux results
Date Thu, 14 Nov 2013 09:19:35 GMT
On 9 November 2013 00:35, Steve Hay <> wrote:
> On 7 November 2013 20:05, Jan Kaluza <> wrote:
>> All cgi*.t tests fails since commit r1491887.
> r1491887 restored the running of the tests in t/modperl/local_env.t,
> which itself fails for me on Windows. I've been looking at why, but
> can't quite figure it out.
> All but the last test pass. The last test checks that a copy of %ENV
> taken before making local()ized changes to it matches the restored
> %ENV after the local() scope has been exited. It fails because %ENV
> has one more item in it than it did originally. The original had a key
> named 'SystemRoot'; the restored version has that and another key
> named 'SYSTEMROOT' too. On Windows, environment variable names (like
> file names and registry keys and many other things) are
> case-preserving but case-insensitive; clearly something has gone amiss
> there.
> The extra key creeps in within t_cmp(): it isn't there before
>     t_debug("expected: " . struct_as_string(0, $expected));
> but is there after it! Inside struct_as_string() we mistakenly go into
> the !HAS_DUMPER code path due to a wrong test for perl >= 5.6.0 [which
> I've just fixed in r1540227] and do this:
>             my @data = ();
>             for my $key (keys %{ $_[0] }) {
>                 push @data,
>                     "$key => " .
>                     struct_as_string($level+1, $_[0]->{$key});
>             }
>             return join "\n", "{", map({"$pad$_,"} @data), "$spad\}";
> which looks perfectly reasonable but wrongly causes the extra key to
> appear in %ENV. (Perhaps it gets SystemRoot from keys() but that gets
> uppercased when looking up the value a few lines later, causing the
> SYSTEMROOT key to be auto-vivified? I haven't checked that theory yet
> though.)

That seems to be the problem: If I insert this:

    my $old1 = join "\n", grep /^sy/i, keys %copy_ENV;
    my $dummy1 = $copy_ENV{SystemRoot};
    my $new1 = join "\n", grep /^sy/i, keys %copy_ENV;

    my $old2 = join "\n", grep /^sy/i, keys %ENV;
    my $dummy2 = $ENV{SystemRoot};
    my $new2 = join "\n", grep /^sy/i, keys %ENV;

just before:

    ok t_cmp(\%copy_ENV, \%ENV, "\%ENV was restored correctly");

in t/response/ModPerl/ then I get:

# Before:
# SystemRoot
# After:
# SystemRoot
# Before:
# SystemRoot
# After:
# SystemRoot

so the magical %ENV (but obviously not the lexical %copy_ENV)
originally has only SystemRoot in it, but gets SYSTEMROOT in it too
after looking up SystemRoot [sic]!

> I'm struggling to understand the handling of %ENV in both perl and
> mod_perl, but running the code outside of the mod_perl
> environment I can't reproduce the problem, so it seems like something
> in mod_perl, perhaps in modperl_env.c, that is at fault.
> Is it missing the "magic" that perl has to effect the
> case-insensitivity? [...]

Perl sets up a magic vtable for %ENV & elements in mg_vtable.h (order
is get/set/len/clear//free/copy/dup/local):

PL_magic_vtables[want_vtbl_env] = { 0, Perl_magic_set_all_env, 0,
Perl_magic_clear_all_env, 0, 0, 0, 0 };
PL_magic_vtables[want_vtbl_envelem] = { 0, Perl_magic_setenv, 0,
Perl_magic_clearenv, 0, 0, 0, 0 };

which mod_perl overrides in modperl_env.c (omitting copy/dup/local...):

static MGVTBL MP_vtbl_env = {0, modperl_env_magic_set_all, 0,
modperl_env_magic_clear_all, 0 };
static MGVTBL MP_vtbl_envelem = {0, modperl_env_magic_set, 0,
modperl_env_magic_clear, 0 };
StructCopy(&MP_vtbl_env, &PL_vtbl_env, MGVTBL);
StructCopy(&MP_vtbl_envelem, &PL_vtbl_envelem, MGVTBL);

It looks like Perl's magic uppercases %ENV keys, at least on creating
%ENV: On my system the output of 'set' (to show allow environment
variables) shows mixed case:

>set | findstr /i systemroot

but a Data::Dumper dump (at least) of %ENV shows uppercase:

>perl -MData::Dumper -le "print Dumper(\%ENV)" | findstr /i systemroot
        'SYSTEMROOT' => 'C:\\Windows',

The environment set up for mod_perl in ap_add_common_vars(), called
from modperl_env.c's modperl_env_request_populate(), explicitly sets
up SystemRoot (in mixed case):

env2env(e, "SystemRoot");

hence the variable appears in the original %ENV in mixed case. I'm
still not clear how the uppercase version appears after looking up the
mixed case version, though, especially since neither Perl's nor
mod_perl's magic vtable have 'get' fields anyway. I'm clearly missing
the piece of the puzzle that allows for case-insensitive lookups.

I see the same behaviour on the httpd24 branch, so it's not something
I've done in merging the threading branch into that. And I'd forgotten
that I also see the same behaviour on the trunk (with httpd-2.2.25)
too. I was sure that all tests passed on trunk, but this is all using
perl-5.19.5 rather than a stable 5.18.x, so presumably that's where
the trouble has crept in...

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message