use strict;
use base 'Catalyst::Engine::CGI';
-use FCGI;
+eval "use FCGI";
+die "Please install FCGI\n" if $@;
=head1 NAME
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;
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
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
*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
# 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/
)
)
-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