On 9 November 2013 00:35, Steve Hay <steve.m....@googlemail.com> wrote: > On 7 November 2013 20:05, Jan Kaluza <jkal...@redhat.com> 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; t_debug("Before:\n$old1\nAfter:\n$new1"); my $old2 = join "\n", grep /^sy/i, keys %ENV; my $dummy2 = $ENV{SystemRoot}; my $new2 = join "\n", grep /^sy/i, keys %ENV; t_debug("Before:\n$old2\nAfter:\n$new2"); just before: ok t_cmp(\%copy_ENV, \%ENV, "\%ENV was restored correctly"); in t/response/ModPerl/local_env.pm then I get: # Before: # SystemRoot # After: # SystemRoot # Before: # SystemRoot # After: # SYSTEMROOT # 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 local_env.pm 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 SystemRoot=C:\Windows 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: dev-unsubscr...@perl.apache.org For additional commands, e-mail: dev-h...@perl.apache.org