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.302';
3 63     63   1467 use strict;
  63         103  
  63         2535  
4 63     63   23499 use POSIX 'WNOHANG';
  63         227559  
  63         498  
5 63     63   43824 use HTTP::Proxy;
  63         115  
  63         33191  
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 34     34 1 259 my $self = shift;
16 34         1254 $self->kids( [] );
17 34         1334 $self->select( IO::Select->new( $self->proxy->daemon ) );
18             }
19              
20             sub run {
21 103     103 1 322 my $self = shift;
22 103         534 my $proxy = $self->proxy;
23 103         749 my $kids = $self->kids;
24              
25             # check for new connections
26 103         656 my @ready = $self->select->can_read(1);
27 103         26602384 for my $fh (@ready) { # there's only one, anyway
28              
29             # single-process proxy (useful for debugging)
30 82 100       931 if ( $self->max_clients == 0 ) {
31 6         58 $proxy->max_keep_alive_requests(1); # do not block simultaneous connections
32 6         115 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS",
33             "No fork allowed, serving the connection" );
34 6         86 $proxy->serve_connections($fh->accept);
35 6         316 $proxy->new_connection;
36 6         25 next;
37             }
38              
39 76 50       654 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 76         894 my $conn = $fh->accept;
49 76         115900 my $child = fork;
50 76 50       2576 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 76 100       1918 if ($child) {
60 54         3453 $conn->close;
61 54         6343 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", "Forked child process $child" );
62 54         3261 push @$kids, $child;
63             }
64              
65             # the child process handles the whole connection
66             else {
67 22         1723 $SIG{INT} = 'DEFAULT';
68 22         1295 $proxy->serve_connections($conn);
69 22         11200 exit; # let's die!
70             }
71             }
72              
73 81 100       1445 $self->reap_zombies if @$kids;
74             }
75              
76             sub stop {
77 12     12 1 37 my $self = shift;
78 12         237 my $kids = $self->kids;
79              
80             # wait for remaining children
81             # EOLOOP
82 12         191 kill INT => @$kids;
83 12         83 $self->reap_zombies while @$kids;
84             }
85              
86             # private reaper sub
87             sub reap_zombies {
88 75     75 1 238 my $self = shift;
89 75         857 my $kids = $self->kids;
90 75         1127 my $proxy = $self->proxy;
91              
92 75         180 while (1) {
93 97         1383 my $pid = waitpid( -1, WNOHANG );
94 97 100 100     1368 last if $pid == 0 || $pid == -1; # AS/Win32 returns negative PIDs
95 22         122 @$kids = grep { $_ != $pid } @$kids;
  54         222  
96 22         81 $proxy->{conn}++; # Cannot use the interface for RO attributes
97 22         190 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", "Reaped child process $pid" );
98 22         180 $proxy->log( HTTP::Proxy::PROCESS, "PROCESS", @$kids . " remaining kids: @$kids" );
99             }
100             }
101              
102             1;
103              
104             __END__