leocharre has asked for the wisdom of the Perl Monks concerning the following question:

I had a really strange error on my cgi app.
I also found a solution.. and it makes about as much sense to me as my ex girlfriend..

It deals with Time::Format 1.09
A certain time format string actually crashes my cgi with no mercy- with silence to STDERR or STDOUT (yes, i'm tailing the logfile, etc etc etc ..) - but called via regular cli, it causes no problems.

In my CGI app, I had a crash recently that I tracked down to this:

my $last_login = 1231357784; my $ll = Time::Format::time_format( 'Weekday Month dth yyyy, h:mm', $l +ast_login ); print STDERR "We should get here\n"; # but we dont
However this works swell:
my $last_login = 1231357784; my $ll = Time::Format::time_format( 'mm/dd/yy hh:mm', $last_login ); print STDERR "We should get here\n"; # and we do

I thought maybe I had a messed up time format string.. But I had been using this Time::Format string for a while.. so.. Just for curiosity.. I wrote this cgi, a simple script with no crazy deps, none of my other code etc.. just a real sanity check here..

#!/usr/bin/perl -w use strict; use CGI; use Time::Format; my $last_login = 1231357784; my $c = new CGI; print $c->header; #my $a = Time::Format::time_format( 'mm/dd/yy hh:mm', $last_login ); # + time format string i see working fine my $a = Time::Format::time_format( 'Weekday Month dth yyyy, h:mm', $la +st_login ); # time format string that crashes print "last login $a";

Which, guess what... crashes.
However - If I run from the command line...

root@thalidomide# perl /var/www/cgi-bin/script.cgi
Content-Type: text/html; charset=ISO-8859-1

last login Wednesday January 7th 2009, 14:49

So I changed it around to use the other string 'mm/dd/yy hh:mm' and it works again via cgi.. ... WTF??

As well as via obviously, cli.. works fine and outputs

root@thalidomide# perl /var/www/cgi-bin/script.cgi
Content-Type: text/html; charset=ISO-8859-1

last login 01/07/09 14:49
update

(I should have noted that this error did not happen on all servers, some worked fine. This is in regards to a failing server.. )

From man Time::Format: Time::Format_XS is optional but will make C<%time> and C<time_format> much faster. The version of Time::Format_XS installed must match the version of Time::Format installed; otherwise Time::Format will not use it (and will issue a warning).

I didn't get a warning. I got the silent treatment. (Much like my ex girlfriend when she left me.. (it'll take a coder to find a pattern here))

So.. on the server that crashes (via cgi, no servers crash on cli).
Time::Format_XS 1.02
Time::Format 1.09

Thus.. cpan Time::Format_XS .. we *have* the most current version.

Thus.. I look on the working server.. what is the version of Time::Format and Time::Format_XS there? Same Time::Format.. Missing Time::Format_XS.

Go back to the server crashing via cgi.. locate Format_XS.pm .. rm it, voila. Works fine, without using BEGIN { $Time::Format::NOXS=1; }.

Still unresolved .. why did it always work via cli? Why only on one time format string but not another??? Very interesting.

Thanks to Charles Hamilton for solving that. Perlbotics, for figuring out a solution in the first place and where to look!

Replies are listed 'Best First'.
Re: Time::Format string that works in cli crashes cgi
by Perlbotics (Archbishop) on Jan 07, 2009 at 21:03 UTC

    FWIW, your CGI-script works fine here: perl v5.10.0, openSuSE 11.1, Time::Format 1.09. Works both - with root and non-privileged users.

    However, It seams that Time::Format is checking if an XS version is available. Maybe it is crashes while doing so or while doing the parsing later on?

    # Here we go through a bunch of tests to decide whether we can use the # XS module, or if we need to load and compile the perl-only # subroutines (which are stored in __DATA__). my $load_perlonly = 0; $load_perlonly = 1 if defined $Time::Format::NOXS && $Time::Format: +:NOXS;
    Maybe adding
    ... BEGIN { $Time::Format::NOXS=1; } use Time::Format; ...
    to your CGI helps?

    Update: forgot to add: while doing the parsing later on
    Update2: clarified, that Time::Format::NOXS had to be set prior to using the module.
    Update3: Now, since this experiment was successful, it seems that the problem is correlated with the usage of the XS based module (or something depending on that).
    Things you could try:

    • as AM said: check under your webservers UID, then
    • check/compare environment variables, esp. LANG, LD_LIBRARY_PATH, PERL*
    • strace perl script.cgi (under both UIDs)
    • re-compile/re-install the XS module
    • ...

      Thank you Perlbotics!

      I placed

      BEGIN{ $Time::Format:: NOXS=1;} use Time::Format;

      And now it works! Now.. I see your explanation.. but .. still.. this is cryptic as all heck..

      Why does this crash via cgi but not cli???

        The error log would have a clue, probably permissions.

      Thank you.. But.. nah.. didn't make it work.

      GNU/Linux 2.6.15 FC5, perl v5.8.8, Time::Format 1.09, Apache 2.2.0

      Really weird, I wouldn't wish this on anyone- it took me a while to find where the code was bonking.. I mean a while while.

      No message but 'premature end of script headers', maybe that string is somehow triggering a print to STDOUT - but I don't see a character in cli output..

Re: Time::Format string that works in cli crashes cgi
by scorpio17 (Canon) on Jan 07, 2009 at 22:27 UTC
    I've seen something like this before. In my case, I was using the GD module to generate a little .gif image on a web page. It would work on the command line but not in the browser. Turns out it was a permission problem - not on the cgi script, but on the oject file the GD.pm module wraps. Once I did a 'chmod 755' on everything, it started working.
Re: Time::Format string that works in cli crashes cgi
by Anonymous Monk on Jan 07, 2009 at 21:57 UTC
    Presumably when run as a cgi script it is not running as root, but as an unprivileged user. What happens if you run it from the command line as that unprivileged user?