File Coverage

blib/lib/AnyEvent/Fork/Serve.pm
Criterion Covered Total %
statement 29 43 67.4
branch 11 22 50.0
condition 3 4 75.0
subroutine 1 3 33.3
pod 0 2 0.0
total 44 74 59.4


line stmt bran cond sub pod time code
1             package AnyEvent::Fork::Serve;
2              
3             our $OWNER; # pid of process "owning" us
4              
5             # commands understood:
6             # e_val perlcode string...
7             # f_ork
8             # h_andle + fd
9             # a_rgs string...
10             # r_un func
11              
12             # the goal here is to keep this simple, small and efficient
13             sub serve {
14 3     3 0 24 local $^W = 0; # avoid spurious warnings
15              
16 3         28 undef &me; # free a tiny bit of memory
17              
18 3         5 my $master = shift;
19              
20 3         7 my @arg;
21              
22 3         3 my ($cmd, $fd);
23              
24 3         44 local $SIG{CHLD} = 'IGNORE';
25              
26             my $error = sub {
27 0     0   0 warn "[$0] ERROR: $_[0]\n";
28 0         0 last;
29 3         9 };
30              
31 3         3 while () {
32             # we must not ever read "too much" data, as we might accidentally read
33             # an IO::FDPass::send request.
34              
35 7         16 my $len;
36 7   100     338020 sysread $master, $len, 5 - length $len, length $len or last
37             while 5 > length $len;
38 6         81 ($cmd, $len) = unpack "a L", $len;
39              
40 6         13 my $buf;
41 6   50     51 sysread $master, $buf, $len - length $buf, length $buf or last
42             while $len > length $buf;
43              
44 6 100       46 if ($cmd eq "h") {
    50          
    100          
    50          
    0          
45 2         22 require IO::FDPass;
46 2         36 $fd = IO::FDPass::recv (fileno $master);
47 2 50       8 $fd >= 0 or $error->("AnyEvent::Fork::Serve: fd_recv() failed: $!");
48 2 50       42 open my $fh, "+<&=$fd" or $error->("AnyEvent::Fork::Serve: open (fd_recv) failed: $!");
49 2         6 push @arg, $fh;
50              
51             } elsif ($cmd eq "a") {
52 0         0 push @arg, unpack "(w/a*)*", $buf;
53              
54             } elsif ($cmd eq "f") {
55 2         1086 my $pid = fork;
56              
57 2 100       67 if ($pid eq 0) {
58 1         63 $0 = "AnyEvent::Fork of $OWNER";
59 1         19 $master = pop @arg;
60              
61             } else {
62 1         14 pop @arg;
63              
64 1 50       42 $pid
65             or $error->("AnyEvent::Fork::Serve: fork() failed: $!");
66             }
67              
68             } elsif ($cmd eq "e") {
69 2         16 ($cmd, @_) = unpack "(w/a*)*", $buf;
70              
71             # $cmd is allowed to access @_ and @arg, and nothing else
72             package main;
73 2         393 eval $cmd;
74 0 0       0 $error->("$@") if $@;
75            
76             } elsif ($cmd eq "r") {
77             # we could free &serve etc., but this might just unshare
78             # memory that could be shared otherwise.
79 0         0 @_ = ($master, @arg);
80 0         0 $0 = "$buf of $OWNER";
81             package main;
82 0         0 goto &$buf;
83              
84             } else {
85 0         0 $error->("AnyEvent::Fork::Serve received unknown request '$cmd' - stream corrupted?");
86             }
87             }
88              
89 1         29 shutdown $master, 1;
90 1         57498 exit; # work around broken win32 perls
91             }
92              
93             # the entry point for new_exec
94             sub me {
95             #$^F = 2; # should always be the case
96              
97 0 0   0 0   open my $fh, "+<&=$ARGV[0]"
98             or die "AnyEvent::Fork::Serve::me unable to open communication socket: $!\n";
99              
100 0           $OWNER = $ARGV[1];
101              
102 0           $0 = "AnyEvent::Fork/exec of $OWNER";
103              
104 0           @ARGV = ();
105 0           @_ = $fh;
106 0           goto &serve;
107             }
108              
109             1
110