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

I have a strange bug in which regexes stop working after a period of time in a long running script.

This script is running under FCGI::Engine and uses Module::Refresh. After experimentation and speaking with the maintainer of FCGI::Engine, I don't think it is those modules at fault, though I am not sure. In particular when started and after a refresh, everything works fine.

After some point (not sure what triggers it), some regular experessions in the script fail to evaluate correctly. For example a

$test =~ /$test2/ when both variables are simple strings and the same strings will not evaluate to true. It's as if they become tainted.

Any ideas?

Replies are listed 'Best First'.
Re: Normal regexes stop working
by Corion (Patriarch) on Oct 24, 2010 at 16:39 UTC

    What are their "same values"? Maybe there is whitespace in one but not the other? Without more data, it's hard to be more specific. Maybe at one time during the run of your script, you modify the environment, and set some filehandle to binmode or a different encoding, which makes subsequent reads fail. You'll have to do some testing and inspection of your access logs to identify which process handled which sequence of requests that ultimately fails.

Re: Normal regexes stop working
by jethro (Monsignor) on Oct 24, 2010 at 18:27 UTC
    Use Data::Dumper to print these values and set $Data::Dumper::Useqq=1. You will see exactly what is in those strings, complete with invisible characters, tabs or spaces...
      OK, did that.

      Here was the printout from the first failure after making that change:

      warn qq(\nDILBERT 1a: "), Dumper($q_meta), " ", Dumper($page_title) if + $is_dilbert; DILBERT 1a: "$VAR1 = "Haji\\ Ayub\\ Afridi"; $VAR1 = "Haji Ayub Afridi";"
        Thx--I haven't figured out the error yet, but I did make some progress.

        I found that if $q was set to $VAR1 = "\n\302\240"; the time before then it doesn't work thereafter.

Re: Normal regexes stop working
by JavaFan (Canon) on Oct 24, 2010 at 17:02 UTC
    Tainted has nothing to do whether regexes match or not. I expect the variables either don't contain what you expect, or $test2 contains one or more characters that are special to the regular expression engine.

    Do you have an example of a $test and a $test2 that you expect to match, but don't?

      Sorry, I didn't mean the perl form of tainted--but the english form. I can literally set the strings to the same value and it fails. Also weird, I can detect that failure case, and branch code there and do a new regex with the same variables and that one succeeds.
        If you keep refusing to give actual example values, or even better, a small stand alone code sample that exhibits the problem, I do not think you'll get anywhere near a useful answer.
        As a double check I also had it do $test eq $test2 when printing out this error case, and that evaluated to 1. When could that work but $test =~ /$test2/ fail?
Re: Normal regexes stop working
by Anonymous Monk on Oct 24, 2010 at 17:12 UTC
    I think its because regular expressions have syntax of their own, and it seems you want to use eq
    die if 'stu\d' =~ /stu\d/; die if 'stu\d' =~ 'stu\d'; die if 'stu\d' =~ /\Qstu\d\E/; __END__ Died at - line 3.
      I made this case simple, but in the general case I'm actually doing this:
      my $q_meta = quotemeta($q); my $tmp_test = ($test =~ /$q_meta/i) || 0;
      So it should escape all those special characters.
Re: Normal regexes stop working
by aquarium (Curate) on Oct 24, 2010 at 22:36 UTC
    not sure if this is your problem but sounds like it. i don't have direct experience with FCGI::Engine, but a couple of CGI perl apache modules i used a while ago...you need to make sure to initialize variables, or an instance/session can pickup values from previous one. so in the end init all variables or pick up their values from a form/url via param.
    the hardest line to type correctly is: stty erase ^H
      Thx--I haven't figured out the error yet, but I did make some progress.

      I found that if $q was set to $VAR1 = "\n\302\240"; the time before then it doesn't work thereafter.

        At some point you are saying your regex fails when you do:
        $x =~ /$y/;
        yes? That being the case, then do this for debugging:
        my $match = $x =~ /$y/; printf "x=%s, y=%s\n", $x, $y unless $match;
        So this will print out something every time they don't match, which is the case you are looking for, right?