File Coverage

blib/lib/HTTP/Proxy/Engine/Legacy.pm
Criterion Covered Total %
statement 50 58 86.2
branch 10 14 71.4
condition 3 3 100.0
subroutine 7 7 100.0
pod 4 4 100.0
total 74 86 86.0


line stmt bran cond sub pod time code
1             package HTTP::Proxy::Engine::Legacy;
2             $HTTP::Proxy::Engine::Legacy::VERSION = '0.304';
3 66     66   1469 use strict;
  66         99  
  66         3119  
4 66     66   24626 use POSIX 'WNOHANG';
  66         271754  
  66         1276  
5 66     66   52897 use HTTP::Proxy;
  66         129  
  66         37268  
6              
7             our @ISA = qw( HTTP::Proxy::Engine );
8             our %defaults = (
9             max_clients => 12,
10             );
11              
12             __PACKAGE__->make_accessors( qw( kids select ), keys %defaults );
13              
14             sub start {
15 36     36 1 468 my $self = shift;
16 36         1019 $self->kids( [] );
17 36         1426 $self->select( IO::Select->new( $self->proxy->daemon ) );
18             }
19              
20             sub run {
21 104     104 1 309 my $self = shift;
22 104         653 my $proxy = $self->proxy;
23 104         725 my $kids = $self->kids;
24              
25             # check for new connections
26 104         591 my @ready = $self->select->can_read(1);
27 104         24496205 for my $fh (@ready) { # there's only one, anyway
28              
29             # single-process proxy (useful for debugging)
30 84 100       891 if ( $self->max_clients == 0 ) {
31 6         73 $proxy->max_keep_alive_requests(1); # do not block simultaneous connections
32 6         96 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS",
33             "No fork allowed, serving the connection" );
34 6         104 $proxy->serve_connections($fh->accept);
35 6         395 $proxy->new_connection;
36 6         121 next;
37             }
38              
39 78 50       420 if ( @$kids >= $self->max_clients ) {
40 0         0 $proxy->log( HTTP::Proxy::ERROR, "PROCESS",
41             "Too many child process, serving the connection" );
42 0         0 $proxy->serve_connections($fh->accept);
43 0         0 $proxy->new_connection;
44 0         0 next;
45             }
46              
47             # accept the new connection
48 78         1103 my $conn = $fh->accept;
49 78         139083 my $child = fork;
50 78 50       2856 if ( !defined $child ) {
51 0         0 $conn->close;
52 0         0 $proxy->log( HTTP::Proxy::ERROR, "PROCESS", "Cannot fork" );
53 0 0       0 $self->max_clients( $self->max_clients - 1 )
54             if $self->max_clients > @$kids;
55 0         0 next;
56             }
57              
58             # the parent process
59 78 100       1961 if ($child) {
60 55         3754 $conn->close;
61 55         7413 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", "Forked child process $child" );
62 55         4027 push @$kids, $child;
63             }
64              
65             # the child process handles the whole connection
66             else {
67 23         2023 $SIG{INT} = 'DEFAULT';
68 23         1254 $proxy->serve_connections($conn);
69 23         18415 exit; # let's die!
70             }
71             }
72              
73 81 100       1785 $self->reap_zombies if @$kids;
74             }
75              
76             sub stop {
77 13     13 1 89 my $self = shift;
78 13         179 my $kids = $self->kids;
79              
80             # wait for remaining children
81             # EOLOOP
82 13         123 kill INT => @$kids;
83 13         99 $self->reap_zombies while @$kids;
84             }
85              
86             # private reaper sub
87             sub reap_zombies {
88 75     75 1 305 my $self = shift;
89 75         680 my $kids = $self->kids;
90 75         1204 my $proxy = $self->proxy;
91              
92 75         194 while (1) {
93 98         1438 my $pid = waitpid( -1, WNOHANG );
94 98 100 100     1305 last if $pid == 0 || $pid == -1; # AS/Win32 returns negative PIDs
95 23         117 @$kids = grep { $_ != $pid } @$kids;
  55         180  
96 23         69 $proxy->{conn}++; # Cannot use the interface for RO attributes
97 23         193 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", "Reaped child process $pid" );
98 23         167 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", @$kids . " remaining kids: @$kids" );
99             }
100             }
101              
102             1;
103              
104             __END__