Reformatted documentation
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / FastCGI.pm
index d832bea..f3f250a 100644 (file)
@@ -2,7 +2,8 @@ package Catalyst::Engine::FastCGI;
 
 use strict;
 use base 'Catalyst::Engine::CGI';
-use FCGI;
+eval "use FCGI";
+die "Please install FCGI\n" if $@;
 
 =head1 NAME
 
@@ -16,9 +17,7 @@ This is the FastCGI engine.
 
 This class overloads some methods from C<Catalyst::Engine::CGI>.
 
-=over 4
-
-=item $self->run($c, $listen, { option => value, ... })
+=head2 $self->run($c, $listen, { option => value, ... })
  
 Starts the FastCGI server.  If C<$listen> is set, then it specifies a
 location to listen for FastCGI requests;
@@ -37,6 +36,9 @@ Options may also be specified;
                   interrupted by Ctrl+C
   nproc           Specify a number of processes for
                   FCGI::ProcManager
+  pidfile         Specify a filename for the pid file
+  manager         Specify a FCGI::ProcManager sub-class
+  detach          Detach from console
 
 =cut
 
@@ -62,28 +64,49 @@ sub run {
 
     $options ||= {};
 
+    my %env;
+
     my $request =
-      FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%ENV, $sock,
+      FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%env, $sock,
         ( $options->{nointr} ? 0 : &FCGI::FAIL_ACCEPT_ON_INTR ),
       );
 
     my $proc_manager;
 
-    if ( $listen and ( $options->{nproc} || 1 ) > 1 ) {
-        require FCGI::ProcManager;
-        $proc_manager =
-          FCGI::ProcManager->new( { n_processes => $options->{nproc} } );
-        $proc_manager->pm_manage();
+    if ($listen) {
+        $options->{manager} ||= "FCGI::ProcManager";
+        $options->{nproc}   ||= 1;
+
+        $self->daemon_fork() if $options->{detach};
+
+        if ( $options->{manager} ) {
+            eval "use $options->{manager}; 1" or die $@;
+
+            $proc_manager = $options->{manager}->new(
+                {
+                    n_processes => $options->{nproc},
+                    pid_fname   => $options->{pidfile},
+                }
+            );
+
+            # detach *before* the ProcManager inits
+            $self->daemon_detach() if $options->{detach};
+
+            $proc_manager->pm_manage();
+        }
+        elsif ( $options->{detach} ) {
+            $self->daemon_detach();
+        }
     }
 
     while ( $request->Accept >= 0 ) {
         $proc_manager && $proc_manager->pm_pre_dispatch();
-        $class->handle_request;
+        $class->handle_request( env => \%env );
         $proc_manager && $proc_manager->pm_pre_dispatch();
     }
 }
 
-=item $self->write($c, $buffer)
+=head2 $self->write($c, $buffer)
 
 =cut
 
@@ -100,11 +123,42 @@ sub write {
     *STDOUT->syswrite($buffer);
 }
 
+=head2 $self->daemon_fork()
+
+Performs the first part of daemon initialisation.  Specifically,
+forking.  STDERR, etc are still connected to a terminal.
+
+=cut
+
+sub daemon_fork {
+    require POSIX;
+    fork && exit;
+}
+
+=head2 $self->daemon_detach( )
+
+Performs the second part of daemon initialisation.  Specifically,
+disassociates from the terminal.
+
+However, this does B<not> change the current working directory to "/",
+as normal daemons do.  It also does not close all open file
+descriptors (except STDIN, STDOUT and STDERR, which are re-opened from
+F</dev/null>).
+
+=cut
+
+sub daemon_detach {
+    my $self = shift;
+    print "FastCGI daemon started (pid $$)\n";
+    open STDIN,  "+</dev/null" or die $!;
+    open STDOUT, ">&STDIN"     or die $!;
+    open STDERR, ">&STDIN"     or die $!;
+    POSIX::setsid();
+}
+
 1;
 __END__
 
-=back
-
 =head1 WEB SERVER CONFIGURATIONS
 
 =head2 Apache 1.x, 2.x
@@ -114,7 +168,7 @@ control the running of your FastCGI processes.
 
     # Launch the FastCGI processes
     FastCgiIpcDir /tmp
-    FastCgiServer /var/www/MyApp/script/myapp_fastcgi.pl -idle_timeout 300 -processes 5
+    FastCgiServer /var/www/MyApp/script/myapp_fastcgi.pl -idle-timeout 300 -processes 5
     
     <VirtualHost *>
         ScriptAlias / /var/www/MyApp/script/myapp_fastcgi.pl/