Updated fcgi engine for multi process external support
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Engine / FastCGI.pm
1 package Catalyst::Engine::FastCGI;
2
3 use strict;
4 use base 'Catalyst::Engine::CGI';
5 use FCGI;
6
7 =head1 NAME
8
9 Catalyst::Engine::FastCGI - FastCGI Engine
10
11 =head1 DESCRIPTION
12
13 This is the FastCGI engine.
14
15 =head1 OVERLOADED METHODS
16
17 This class overloads some methods from C<Catalyst::Engine::CGI>.
18
19 =over 4
20
21 =item $self->run($c, $listen, { option => value, ... })
22  
23 Starts the FastCGI server.  If C<$listen> is set, then it specifies a
24 location to listen for FastCGI requests;
25
26   Form            Meaning
27   /path           listen via Unix sockets on /path
28   :port           listen via TCP on port on all interfaces
29   hostname:port   listen via TCP on port bound to hostname
30
31 Options may also be specified;
32
33   Option          Meaning
34   leave_umask     Set to 1 to disable setting umask to 0
35                   for socket open
36   nointr          Do not allow the listener to be
37                   interrupted by Ctrl+C
38   nproc           Specify a number of processes for
39                   FCGI::ProcManager
40
41 =cut
42
43 sub run {
44     my ( $self, $class, $listen, $options ) = @_;
45
46     my $sock;
47     if ($listen) {
48         my $old_umask = umask;
49         unless ( $options->{leave_umask} ) {
50             umask(0);
51         }
52         $sock = FCGI::OpenSocket( $listen, 100 )
53           or die "failed to open FastCGI socket; $!";
54         unless ( $options->{leave_umask} ) {
55             umask($old_umask);
56         }
57     }
58     else {
59         -S STDIN
60           or die "STDIN is not a socket; specify a listen location";
61     }
62
63     $options ||= {};
64
65     my $request =
66       FCGI::Request( \*STDIN, \*STDOUT, \*STDERR, \%ENV, $sock,
67         ( $options->{nointr} ? 0 : &FCGI::FAIL_ACCEPT_ON_INTR ),
68       );
69
70     my $proc_manager;
71
72     if ( $listen and ( $options->{nproc} || 1 ) > 1 ) {
73         require FCGI::ProcManager;
74         $proc_manager =
75           FCGI::ProcManager->new( { n_processes => $options->{nproc} } );
76         $proc_manager->pm_manage();
77     }
78
79     while ( $request->Accept >= 0 ) {
80         $proc_manager && $proc_manager->pm_pre_dispatch();
81         $class->handle_request;
82         $proc_manager && $proc_manager->pm_pre_dispatch();
83     }
84 }
85
86 =item $self->write($c, $buffer)
87
88 =cut
89
90 sub write {
91     my ( $self, $c, $buffer ) = @_;
92
93     unless ( $self->{_prepared_write} ) {
94         $self->prepare_write($c);
95         $self->{_prepared_write} = 1;
96     }
97
98     # FastCGI does not stream data properly if using 'print $handle',
99     # but a syswrite appears to work properly.
100     *STDOUT->syswrite($buffer);
101 }
102
103 =back
104
105 =head1 SEE ALSO
106
107 L<Catalyst>, L<FCGI>.
108
109 =head1 AUTHORS
110
111 Sebastian Riedel, <sri@cpan.org>
112
113 Christian Hansen, <ch@ngmedia.com>
114
115 Andy Grundman, <andy@hybridized.org>
116
117 =head1 COPYRIGHT
118
119 This program is free software, you can redistribute it and/or modify it under
120 the same terms as Perl itself.
121
122 =cut
123
124 1;