X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FEngine%2FFastCGI.pm;h=af96ca3d1e53c8af5aa69c552f4da9927edb2807;hb=47c97b64103173bede56e5c773a2e9c3ae028851;hp=f17178f4bf3ba47f996aa0c309d3b3dfb6a37448;hpb=198b0efa0739da9df2e79ac23ea80b63aa651db8;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Engine/FastCGI.pm b/lib/Catalyst/Engine/FastCGI.pm index f17178f..af96ca3 100644 --- a/lib/Catalyst/Engine/FastCGI.pm +++ b/lib/Catalyst/Engine/FastCGI.pm @@ -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. -=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 @@ -55,35 +57,56 @@ sub run { umask($old_umask); } } - else { + elsif ( $^O ne 'MSWin32' ) { -S STDIN or die "STDIN is not a socket; specify a listen location"; } $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 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). + +=cut + +sub daemon_detach { + my $self = shift; + print "FastCGI daemon started (pid $$)\n"; + open STDIN, "+&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 ScriptAlias / /var/www/MyApp/script/myapp_fastcgi.pl/ @@ -155,7 +209,17 @@ This configuration was tested with Lighttpd 1.4.7. ) ) -Or use an external server: +You can also run your application at any non-root location. + + fastcgi.server = ( + "/myapp" => ( + "MyApp" => ( + # same as above + ) + ) + ) + +You can also use an external server: # Start the external server (requires FCGI::ProcManager) $ script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5