Seed the RNG in each FastCGI child process.
Florian Ragwitz [Tue, 3 Feb 2009 10:32:45 +0000 (10:32 +0000)]
From: Andrew Rodland <arodland@comcast.net>
Message-Id: <200902021709.21737.arodland@comcast.net>

Due to the way FastCGI does its business, when running as an "external"
FastCGI, the perl interpreter and the Catalyst app are initialized before the
FCGI process manager does its forking. Since modern versions of Perl seed
rand() "eagerly" on startup, this leads to all of the FastCGI children
inheriting the same RNG state, and very nonrandom behavior (such as CAPTCHAs
that appear to get "stuck").

lib/Catalyst/Engine/FastCGI.pm

index 4af5470..85dee52 100644 (file)
@@ -102,7 +102,7 @@ sub run {
     my $error = \*STDERR; # send STDERR to the web server
        $error = \*STDOUT  # send STDERR to stdout (a logfile)
          if $options->{keep_stderr}; # (if asked to)
-    
+
     my $request =
       FCGI::Request( \*STDIN, \*STDOUT, $error, \%env, $sock,
         ( $options->{nointr} ? 0 : &FCGI::FAIL_ACCEPT_ON_INTR ),
@@ -130,6 +130,9 @@ sub run {
             $self->daemon_detach() if $options->{detach};
 
             $proc_manager->pm_manage();
+
+            # Give each child its own RNG state.
+            srand;
         }
         elsif ( $options->{detach} ) {
             $self->daemon_detach();
@@ -138,11 +141,11 @@ sub run {
 
     while ( $request->Accept >= 0 ) {
         $proc_manager && $proc_manager->pm_pre_dispatch();
-        
+
         $self->_fix_env( \%env );
-        
+
         $class->handle_request( env => \%env );
-        
+
         $proc_manager && $proc_manager->pm_post_dispatch();
     }
 }