File Coverage

blib/lib/Devel/Trace/Fork.pm
Criterion Covered Total %
statement 58 96 60.4
branch 9 38 23.6
condition 6 23 26.0
subroutine 10 11 90.9
pod 0 2 0.0
total 83 170 48.8


line stmt bran cond sub pod time code
1             # -* - perl -*-
2              
3             package Devel::Trace::Fork;
4 1     1   21855 use Devel::Trace;
  1         270  
  1         7  
5 1     1   1086 use Time::HiRes qw(gettimeofday);
  1         1814  
  1         5  
6 1     1   172 use Fcntl ':flock';
  1         6  
  1         99  
7 1     1   5 use Carp;
  1         4  
  1         47  
8 1     1   5 use strict qw(vars subs);
  1         1  
  1         25  
9 1     1   5 use warnings;
  1         1  
  1         332  
10             our $VERSION = '0.11';
11             our ($FH, $FILE, $FH_LOCK, @O);
12             our $_PID2 = $$;
13             our $_PID = $$;
14             our $FLUSH = $ENV{DT_FORK_FLUSH} || 16_384;
15             our $SORT_NEEDED = 0;
16             our %IGNORE_PACKAGES = ('Devel::Trace::Fork' => 1);
17             $| = 1;
18              
19             BEGIN {
20 1     1   14 local $! = undef;
21 1   33     8 $FILE = $ENV{DTRACE_FILE} || "./DTFork.$$";
22 1 50       116 if (open $FH, '>', $FILE) {
23 1         17 print $FH q{> },$^X,q{ },$0,q{ },@ARGV,"\n";
24 1         16 print $FH q{> },$^T,q{ },scalar gettimeofday(),"\n";
25 1         52 close $FH;
26 1         57 open ($FH_LOCK, '>>', "$FILE.x");
27 1         17 print $FH_LOCK "$^T $$ <>\n";
28 1         55 close $FH_LOCK;
29             } else {
30 0         0 croak "Devel::Trace::Fork: Failed to open trace output file $FILE: $!\n",
31             "Use environment variable DTRACE_FILE to set an explicit trace output ",
32             "file name.\n";
33             }
34             }
35              
36 1     1   6 no warnings 'redefine';
  1         1  
  1         1256  
37             sub DB::DB {
38 0 0   0 0 0 return unless $Devel::Trace::TRACE;
39 0         0 my ($p, $f, $l) = caller;
40 0         0 my $t;
41 0 0       0 if ($_PID2 != $$) {
42 0         0 $t = sprintf '%11.6f', gettimeofday()-$^T;
43 0         0 @O = (">> $t:$$: ----------------- NEW PROCESS -----------------\n");
44 0         0 $_PID2 = $$;
45            
46             # In MSWin32, children do not call the END{} block?
47             # Then we need to flush every line :-(
48             # Also, we won't get the -- END OF PROCESS -- indicator at the end :-(
49 0         0 flush();
50 0 0       0 $FLUSH = 0 if $^O eq "MSWin32";
51             }
52 0 0       0 if (!defined $IGNORE_PACKAGES{$p}) {
53 0   0     0 $t ||= sprintf '%11.6f', gettimeofday()-$^T;
54              
55 0         0 my $code = \@{"::_<$f"};
  0         0  
56 0   0     0 my $cde = $code->[$l] || "--- code not available ---\n";
57 0 0       0 if (!defined $f) {
58 0         0 print STDERR "$0 \$f not defined, $p, $f, $l\n";
59             }
60 0 0       0 if (!defined $l) {
61 0         0 print STDERR "$0 \$l not defined $p, $f, $l\n";
62             }
63 0 0       0 if (!defined $code) {
    0          
64 0         0 print STDERR "$0 \$code not defined $p, $f, $l\n";
65             } elsif (!defined $cde) {
66 0         0 print STDERR "$0 \$cde, \$code->[\$l] not defined $p, $f, $l\n";
67             }
68              
69              
70 0         0 push @O, ">> $t:$$:$?:$f:$l: $cde";
71 0 0       0 if (@O > $FLUSH) {
72 0         0 flush();
73             }
74             }
75 0         0 return;
76             }
77              
78             sub flush {
79 1 50 33 1 0 50 if ($$ != $_PID && ! -f "$FILE.x") {
80 0         0 Carp::cluck "Devel::Trace::Fork: ",
81             "possibly appending trace data from $$ ",
82             "after main process $_PID exited.\n";
83 0         0 $SORT_NEEDED = 1;
84             }
85 1 50 33     65 unless (open $FH_LOCK, '>>', "$FILE.x" and flock $FH_LOCK, LOCK_EX) {
86 0         0 carp 'Devel::Trace::Fork: ',
87             "failed to lock output file $FILE before flush: $! $FH_LOCK\n";
88             }
89 1         27 print $FH_LOCK "$$ ", scalar gettimeofday(), "\n";
90              
91 1 50       36 if (open($FH, '>>', $FILE)) {
92 1         12 print $FH @O;
93 1         40 close $FH;
94 1         24 close $FH_LOCK;
95             } else {
96 0         0 carp 'Devel::Trace::Fork: failed to flush ',
97             scalar @O, " lines of output from pid=$$!\n";
98             }
99              
100 1         3 @O = ();
101 1         2 return;
102             }
103              
104             END {
105 1     1   277 $Devel::Trace::TRACE = 0;
106             # *DB::DB = sub { print STDERR "DB::DB end called $$\n"; };
107              
108 1         33 my $t = sprintf '%11.6f', gettimeofday()-$^T;
109 1         7 push @O, ">> $t:$$: -------------- END OF PROCESS ------------------\n";
110 1         4 flush();
111              
112 1 50 33     9 if ($$ == $_PID || $SORT_NEEDED) {
113 1 50 33     11 if ($$ == $_PID && $ENV{DTFORK_ERASE_ON_GOOD_EXIT} && $? == 0) {
      33        
114 0         0 print STDERR "Good exit on $_PID. Erasing $FILE\n";
115 0         0 unlink "$FILE.x";
116 0 0       0 unlink $FILE if $ENV{DTFORK_ERASE_ON_GOOD_EXIT} > 0;
117 0         0 undef $FILE;
118 0         0 $? = 0;
119 0         0 return;
120             }
121 1 50       29 if (open($FH_LOCK, '>>', "$FILE.x")) {
122 1         11 print $FH_LOCK "$$ ", scalar gettimeofday(), "\n";
123 1         17 flock $FH_LOCK, LOCK_EX;
124             }
125              
126 1 50       25 if (open($FH, '<', $FILE)) {
127 1         21 my @P = <$FH>;
128 1         10 close $FH;
129              
130 1         6 @P = sort @P;
131              
132 1 50       81 if (open($FH, '>', $FILE)) {
133 1         5 print $FH @P;
134 1         109 close $FH;
135             } else {
136 0         0 carp 'Devel::Trace::Fork: failed to rewrite sorted output';
137             }
138             } else {
139 0         0 carp 'Devel::Trace::Fork: failed to read final output';
140             }
141              
142 1         10 close $FH_LOCK;
143 1         95 unlink "$FILE.x";
144              
145 1         31 print STDERR "Devel::Trace::Fork output in <$FILE>\n";
146             }
147             }
148              
149             1;
150              
151             __END__