You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Kirk Noda <ki...@nmseg.com> on 2007/12/28 22:15:54 UTC
mod_perl, ENV{'TZ'}, and localtime
Hello,
I'd like to reference the Tues 03 Oct '06 thread with subject:
RE: Using ENV{'TZ'} in mod_perl
http://mail-archives.apache.org/mod_mbox/perl-modperl/200610.mbox/browser
The thread seemed to die off. Still, is there a way to use $ENV{TZ}
to modify the behavior of localtime? I get the same result on
mod_perl 1.99_16 and 2.0.3. PerlTaintCheck is off for
both. POSIX::tzset() does not correct the mis(?)behavior. I'd like
to get this to work with the apache 2.0.52 + mod_perl 1.99_16 setup.
BTW, This did work way back on apache 1.3.27 + mod_perl 1.27.
###
### Test script
###
#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw(tzset tzname);
print "Content-type: text/plain\n\n";
$ENV{'TZ'} = 'US/Eastern';
POSIX::tzset();
my $eastern = localtime();
my ($estd, $edst) = POSIX::tzname();
foreach my $tmp (sort keys %ENV) {
printf("%-30s:%s\n",$tmp,$ENV{$tmp});
}
print "\n";
$ENV{'TZ'} = 'US/Pacific';
POSIX::tzset();
my $pacific = localtime();
my ($pstd, $pdst) = POSIX::tzname();
print
"Eastern: $eastern\n",
"Eastern: std: $estd dst: $edst\n",
"Pacific: $pacific\n",
"Pacific: std: $pstd dst: $pdst\n",
;
###
### Test 1 (fails)
###
GATEWAY_INTERFACE :CGI/1.1
MOD_PERL :mod_perl/2.0.3
MOD_PERL_API_VERSION :2
SERVER_SOFTWARE :Apache/2.2.6 (Fedora)
Eastern: Fri Dec 28 11:59:31 2007
Eastern: std: PST dst: PDT
Pacific: Fri Dec 28 11:59:31 2007
Pacific: std: PST dst: PDT
###
### Test 2 (fails)
###
GATEWAY_INTERFACE :CGI/1.1
MOD_PERL :mod_perl/1.99_16
SERVER_SOFTWARE :Apache/2.0.52 (Red Hat)
Eastern: Fri Dec 28 12:04:04 2007
Eastern: std: PST dst: PDT
Pacific: Fri Dec 28 12:04:04 2007
Pacific: std: PST dst: PDT
###
### Test 3 (works, non mod_perl)
###
GATEWAY_INTERFACE :CGI/1.1
SERVER_SOFTWARE :Apache/2.2.6 (Fedora)
Eastern: Fri Dec 28 15:26:35 2007
Eastern: std: EST dst: EDT
Pacific: Fri Dec 28 12:26:35 2007
Pacific: std: PST dst: PDT
###
### Test 4 (works, really old mod_perl+apache)
###
GATEWAY_INTERFACE :CGI-Perl/1.1
MOD_PERL :mod_perl/1.27
SERVER_SOFTWARE :Apache/1.3.27 (Unix) mod_perl/1.27
AuthMySQL/2.20 PHP/4.2.3 mod_ssl/2.8.11 OpenSSL/0.9.6g
Eastern: Fri Dec 28 15:44:11 2007
Eastern: std: EST dst: EDT
Pacific: Fri Dec 28 12:44:12 2007
Pacific: std: PST dst: PDT
Re: mod_perl, ENV{'TZ'}, and localtime
Posted by Kirk Noda <ki...@nmseg.com>.
At 09:12 PM 12/28/2007, you wrote:
[...]
>The reason this does not work under modperl version 2.0 is because under
>handler "perl-script", %ENV is untied from the C environment. The
[...]
Thanks very much, that works.
Re: mod_perl, ENV{'TZ'}, and localtime
Posted by Michael Schout <ms...@gkg.net>.
Kirk Noda wrote:
> The thread seemed to die off. Still, is there a way to use $ENV{TZ} to
> modify the behavior of localtime?
The reason this does not work under modperl version 2.0 is because under
handler "perl-script", %ENV is untied from the C environment. The
localtime() function is implemented in C, and as a result, it will never
see the changes you made to $ENV{TZ} from mod_perl.
The way I got around this was to use Env::C, and override
CORE::localtime() with something like:
package MyLocaltime;
use Env::C;
sub import {
my $class = shift;
$class->export('CORE::GLOBAL', 'localtime');
}
sub localtime {
my $time = shift;
$time = time unless defined $time;
my $orig_tz = Env::C::getenv('TZ');
Env::C::setenv('TZ', $ENV{TZ}, 1);
my @ret = CORE::localtime($time);
Env::C::setenv('TZ', $orig_tz, 1);
return @ret;
}
The real problem is that this is only safe under a prefork MPM because
it is not thread safe. There really ought to be an option (IMO) where
you can make the untie of %ENV under perl-script to be optional. Maybe
something like PerlOptions +NoUntieEnv or something so that if you are
running under a prefork MPM, you do not need to resort to tactics like
the above.
Regards,
Michael Schout