File Coverage

blib/lib/Acme/Spork.pm
Criterion Covered Total %
statement 21 66 31.8
branch 1 18 5.5
condition 0 7 0.0
subroutine 7 11 63.6
pod 0 3 0.0
total 29 105 27.6


line stmt bran cond sub pod time code
1             package Acme::Spork;
2              
3 1     1   29779 use strict;
  1         2  
  1         43  
4 1     1   5 use warnings;
  1         2  
  1         28  
5 1     1   4 use Carp;
  1         6  
  1         93  
6 1     1   1170 use IO::Handle;
  1         13637  
  1         95  
7              
8             require Exporter;
9             our @ISA = qw(Exporter);
10             our @EXPORT = qw(spork);
11             our @EXPORT_OK = qw(daemonize daemonize_without_close_on);
12              
13 1     1   798 use version;our $VERSION = qv('0.0.8');
  1         2620  
  1         10  
14              
15             our %reopen_stdfhs_to;
16              
17             sub import {
18 1     1   139 shift->export_to_level(1, grep(!/^-/, @_));
19 1 50       7 if(grep /^-reopen_stdfhs$/, @_) {
20 0         0 %reopen_stdfhs_to = (
21             STDIN => [qw(< /dev/null)],
22             STDOUT => [qw(> /dev/null)],
23             STDERR => [qw(>&STDOUT)],
24             );
25             }
26 1         16 return;
27             }
28              
29             sub spork {
30 0     0 0   my $spork = shift;
31 0 0         croak "spork() needs a code ref!" if ref $spork ne 'CODE';
32            
33 0           my $PARENT_WTR = IO::Handle->new;
34 0           my $CHILD_RDR = IO::Handle->new;
35              
36 0           pipe($CHILD_RDR, $PARENT_WTR); # or return/croak ?
37 0           $PARENT_WTR->autoflush(1);
38              
39 0 0         defined (my $kid = fork) or die "Cannot fork: $!\n";
40            
41 0 0         if ($kid) {
42 0           close $PARENT_WTR;
43 0           chomp(my $grandkid_pid = <$CHILD_RDR>);
44 0           close $CHILD_RDR;
45 0           waitpid($kid,0);
46 0           return $grandkid_pid;
47             }
48             else {
49             ## local $SIG{CHLD} = 'IGNORE';
50 0 0         if (!defined &setsid) {
51 0           require POSIX;
52 0           *setsid = *POSIX::setsid;
53             }
54 0           setsid();
55             ##
56            
57 0 0         defined ( my $grandkid = fork) or die "Kid cannot fork: $!\n";
58 0 0         if ($grandkid) {
59 0           close $CHILD_RDR;
60 0           print $PARENT_WTR "$grandkid\n";
61 0           close $PARENT_WTR;
62 0           CORE::exit(0);
63             }
64             else {
65 0           close $CHILD_RDR;
66 0           close $PARENT_WTR;
67            
68 0           for my $stdfh (qw(STDIN STDOUT STDERR)) {
69 0           close $stdfh;
70 0 0 0       if(exists $reopen_stdfhs_to{ $stdfh } && ref $reopen_stdfhs_to{ $stdfh } eq 'ARRAY') {
71 0           eval "open( $stdfh, " . join(', ', map { qq{"$_"} } @{ $reopen_stdfhs_to{ $stdfh } }) . ' );';
  0            
  0            
72 0 0         carp "Could not reopen $stdfh : $@" if $@;
73             # no strict 'refs';
74             # open( $stdfh , @{ $reopen_stdfhs_to{ $stdfh } }) or carp "Could not reopen $stdfh : $!";
75             }
76             }
77            
78             ## if (!defined &setsid) {
79             ## require POSIX;
80             ## *setsid = *POSIX::setsid;
81             ## }
82             ##
83             ## setsid();
84             ## $SIG{CHLD} = 'DEFAULT';
85 0           $spork->(@_);
86 0           CORE::exit(0);
87             }
88             }
89             }
90              
91             sub daemonize {
92 0     0 0   require Proc::Daemon;
93             {
94 0   0       local $SIG{'HUP'} = $SIG{'HUP'} || ''; # workaround until http://rt.cpan.org/Public/Bug/Display.html?id=21453
  0            
95 0           goto &Proc::Daemon::Init;
96             }
97             }
98              
99             sub daemonize_without_close_on {
100 0     0 0   require Proc::Daemon;
101             {
102 1     1   990 no warnings 'redefine';
  1         2  
  1         148  
  0            
103 0     0     local *POSIX::close = sub { return 1; }; # the "without_close_on" part
  0            
104              
105 0   0       local $SIG{'HUP'} = $SIG{'HUP'} || ''; # workaround until http://rt.cpan.org/Public/Bug/Display.html?id=21453
106 0           Proc::Daemon::Init(@_);
107             }
108             }
109              
110             1;
111              
112             __END__