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.303';
3 66     66   1218 use strict;
  66         81  
  66         2195  
4 66     66   19985 use POSIX 'WNOHANG';
  66         203017  
  66         989  
5 66     66   36553 use HTTP::Proxy;
  66         91  
  66         27362  
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 344 my $self = shift;
16 36         707 $self->kids( [] );
17 36         1051 $self->select( IO::Select->new( $self->proxy->daemon ) );
18             }
19              
20             sub run {
21 113     113 1 273 my $self = shift;
22 113         507 my $proxy = $self->proxy;
23 113         469 my $kids = $self->kids;
24              
25             # check for new connections
26 113         538 my @ready = $self->select->can_read(1);
27 113         37025738 for my $fh (@ready) { # there's only one, anyway
28              
29             # single-process proxy (useful for debugging)
30 84 100       666 if ( $self->max_clients == 0 ) {
31 6         69 $proxy->max_keep_alive_requests(1); # do not block simultaneous connections
32 6         82 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS",
33             "No fork allowed, serving the connection" );
34 6         87 $proxy->serve_connections($fh->accept);
35 6         593 $proxy->new_connection;
36 6         133 next;
37             }
38              
39 78 50       464 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         1087 my $conn = $fh->accept;
49 78         106633 my $child = fork;
50 78 50       2307 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       1494 if ($child) {
60 55         2744 $conn->close;
61 55         5556 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", "Forked child process $child" );
62 55         3207 push @$kids, $child;
63             }
64              
65             # the child process handles the whole connection
66             else {
67 23         2040 $SIG{INT} = 'DEFAULT';
68 23         1089 $proxy->serve_connections($conn);
69 23         10224 exit; # let's die!
70             }
71             }
72              
73 90 100       1225 $self->reap_zombies if @$kids;
74             }
75              
76             sub stop {
77 13     13 1 30 my $self = shift;
78 13         111 my $kids = $self->kids;
79              
80             # wait for remaining children
81             # EOLOOP
82 13         105 kill INT => @$kids;
83 13         76 $self->reap_zombies while @$kids;
84             }
85              
86             # private reaper sub
87             sub reap_zombies {
88 80     80 1 239 my $self = shift;
89 80         535 my $kids = $self->kids;
90 80         922 my $proxy = $self->proxy;
91              
92 80         192 while (1) {
93 103         1039 my $pid = waitpid( -1, WNOHANG );
94 103 100 100     1032 last if $pid == 0 || $pid == -1; # AS/Win32 returns negative PIDs
95 23         109 @$kids = grep { $_ != $pid } @$kids;
  55         172  
96 23         66 $proxy->{conn}++; # Cannot use the interface for RO attributes
97 23         184 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", "Reaped child process $pid" );
98 23         193 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", @$kids . " remaining kids: @$kids" );
99             }
100             }
101              
102             1;
103              
104             __END__