File Coverage

blib/lib/Test2/Util.pm
Criterion Covered Total %
statement 109 121 90.0
branch 24 50 48.0
condition 8 25 32.0
subroutine 30 30 100.0
pod 5 6 83.3
total 176 232 75.8


line stmt bran cond sub pod time code
1             package Test2::Util;
2 247     247   12086 use strict;
  247         571  
  247         6998  
3 247     247   1236 use warnings;
  247         444  
  247         9074  
4              
5             our $VERSION = '1.302181';
6              
7 247     247   127004 use POSIX();
  247         2001687  
  247         8060  
8 247     247   1728 use Config qw/%Config/;
  247         441  
  247         12280  
9 247     247   1473 use Carp qw/croak/;
  247         441  
  247         26742  
10              
11             BEGIN {
12 247     247   2844 local ($@, $!, $SIG{__DIE__});
13 247 50       595 *HAVE_PERLIO = eval { require PerlIO; PerlIO->VERSION(1.02); } ? sub() { 1 } : sub() { 0 };
  247         149668  
  247         26257  
14             }
15              
16             our @EXPORT_OK = qw{
17             try
18              
19             pkg_to_file
20              
21             get_tid USE_THREADS
22             CAN_THREAD
23             CAN_REALLY_FORK
24             CAN_FORK
25              
26             CAN_SIGSYS
27              
28             IS_WIN32
29              
30             ipc_separator
31              
32             gen_uid
33              
34             do_rename do_unlink
35              
36             try_sig_mask
37              
38             clone_io
39             };
40 247     247   1584 BEGIN { require Exporter; our @ISA = qw(Exporter) }
  247         17916  
41              
42             BEGIN {
43 247 50   247   55321 *IS_WIN32 = ($^O eq 'MSWin32') ? sub() { 1 } : sub() { 0 };
44             }
45              
46             sub _can_thread {
47 247 50   247   1320 return 0 unless $] >= 5.008001;
48 247 50       20181 return 0 unless $Config{'useithreads'};
49              
50             # Threads are broken on perl 5.10.0 built with gcc 4.8+
51 0 0 0     0 if ($] == 5.010000 && $Config{'ccname'} eq 'gcc' && $Config{'gccversion'}) {
      0        
52 0         0 my @parts = split /\./, $Config{'gccversion'};
53 0 0 0     0 return 0 if $parts[0] > 4 || ($parts[0] == 4 && $parts[1] >= 8);
      0        
54             }
55              
56             # Change to a version check if this ever changes
57 0 0       0 return 0 if $INC{'Devel/Cover.pm'};
58 0         0 return 1;
59             }
60              
61             sub _can_fork {
62 27 50   27   1914 return 1 if $Config{d_fork};
63 0 0       0 return 0 unless IS_WIN32 || $^O eq 'NetWare';
64 0 0       0 return 0 unless $Config{useithreads};
65 0 0       0 return 0 unless $Config{ccflags} =~ /-DPERL_IMPLICIT_SYS/;
66              
67 0         0 return _can_thread();
68             }
69              
70             BEGIN {
71 247     247   1868 no warnings 'once';
  247         640  
  247         20569  
72 247 50   247   1046 *CAN_THREAD = _can_thread() ? sub() { 1 } : sub() { 0 };
73             }
74             my $can_fork;
75             sub CAN_FORK () {
76 39 100   39 1 1486 return $can_fork
77             if defined $can_fork;
78 27         298 $can_fork = !!_can_fork();
79 247     247   1798 no warnings 'redefine';
  247         603  
  247         30135  
80 27 50       617 *CAN_FORK = $can_fork ? sub() { 1 } : sub() { 0 };
81 27         187 $can_fork;
82             }
83             my $can_really_fork;
84             sub CAN_REALLY_FORK () {
85 24 100   24 1 223 return $can_really_fork
86             if defined $can_really_fork;
87 17         945 $can_really_fork = !!$Config{d_fork};
88 247     247   1692 no warnings 'redefine';
  247         516  
  247         57493  
89 17 50       164 *CAN_REALLY_FORK = $can_really_fork ? sub() { 1 } : sub() { 0 };
90 17         59 $can_really_fork;
91             }
92              
93             sub _manual_try(&;@) {
94 2     2   19 my $code = shift;
95 2         5 my $args = \@_;
96 2         3 my $err;
97              
98 2         10 my $die = delete $SIG{__DIE__};
99              
100 2 100 50     5 eval { $code->(@$args); 1 } or $err = $@ || "Error was squashed!\n";
  2         7  
  1         4  
101              
102 2 50       18 $die ? $SIG{__DIE__} = $die : delete $SIG{__DIE__};
103              
104 2         9 return (!defined($err), $err);
105             }
106              
107             sub _local_try(&;@) {
108 218     218   2762 my $code = shift;
109 218         508 my $args = \@_;
110 218         403 my $err;
111              
112 247     247   1794 no warnings;
  247         523  
  247         37633  
113 218         1138 local $SIG{__DIE__};
114 218 100 50     472 eval { $code->(@$args); 1 } or $err = $@ || "Error was squashed!\n";
  218         743  
  207         1174  
115              
116 218         2402 return (!defined($err), $err);
117             }
118              
119             # Older versions of perl have a nasty bug on win32 when localizing a variable
120             # before forking or starting a new thread. So for those systems we use the
121             # non-local form. When possible though we use the faster 'local' form.
122             BEGIN {
123 247     247   1966 if (IS_WIN32 && $] < 5.020002) {
124             *try = \&_manual_try;
125             }
126             else {
127 247         48349 *try = \&_local_try;
128             }
129             }
130              
131             BEGIN {
132 247     247   877 if (CAN_THREAD) {
133             if ($INC{'threads.pm'}) {
134             # Threads are already loaded, so we do not need to check if they
135             # are loaded each time
136             *USE_THREADS = sub() { 1 };
137             *get_tid = sub() { threads->tid() };
138             }
139             else {
140             # :-( Need to check each time to see if they have been loaded.
141             *USE_THREADS = sub() { $INC{'threads.pm'} ? 1 : 0 };
142             *get_tid = sub() { $INC{'threads.pm'} ? threads->tid() : 0 };
143             }
144             }
145             else {
146             # No threads, not now, not ever!
147 247         651 *USE_THREADS = sub() { 0 };
148 247         64420 *get_tid = sub() { 0 };
149             }
150             }
151              
152             sub pkg_to_file {
153 844     844 1 1404 my $pkg = shift;
154 844         1287 my $file = $pkg;
155 844         5281 $file =~ s{(::|')}{/}g;
156 844         1649 $file .= '.pm';
157 844         2125 return $file;
158             }
159              
160             sub ipc_separator() { "~" }
161              
162             my $UID = 1;
163 15120     15120 1 151701 sub gen_uid() { join ipc_separator() => ($$, get_tid(), time, $UID++) }
164              
165             sub _check_for_sig_sys {
166 252     252   25678 my $sig_list = shift;
167 252         2283 return $sig_list =~ m/\bSYS\b/;
168             }
169              
170             BEGIN {
171 247 50   247   1622 if (_check_for_sig_sys($Config{sig_name})) {
172 247         139516 *CAN_SIGSYS = sub() { 1 };
173             }
174             else {
175 0         0 *CAN_SIGSYS = sub() { 0 };
176             }
177             }
178              
179             my %PERLIO_SKIP = (
180             unix => 1,
181             via => 1,
182             );
183              
184             sub clone_io {
185 1200     1200 0 4532 my ($fh) = @_;
186 1200         2943 my $fileno = eval { fileno($fh) };
  1200         4035  
187              
188 1200 100 33     9594 return $fh if !defined($fileno) || !length($fileno) || $fileno < 0;
      66        
189              
190 1199 50       34025 open(my $out, '>&' . $fileno) or die "Can't dup fileno $fileno: $!";
191              
192 1199         3661 my %seen;
193 1199   100     9269 my @layers = HAVE_PERLIO ? grep { !$PERLIO_SKIP{$_} and !$seen{$_}++ } PerlIO::get_layers($fh) : ();
  3112         16853  
194 1199         13033 binmode($out, join(":", "", "raw", @layers));
195              
196 1199         6150 my $old = select $fh;
197 1199         3800 my $af = $|;
198 1199         2606 select $out;
199 1199         2564 $| = $af;
200 1199         3046 select $old;
201              
202 1199         4939 return $out;
203             }
204              
205             BEGIN {
206 247     247   1065 if (IS_WIN32) {
207             my $max_tries = 5;
208              
209             *do_rename = sub {
210             my ($from, $to) = @_;
211              
212             my $err;
213             for (1 .. $max_tries) {
214             return (1) if rename($from, $to);
215             $err = "$!";
216             last if $_ == $max_tries;
217             sleep 1;
218             }
219              
220             return (0, $err);
221             };
222             *do_unlink = sub {
223             my ($file) = @_;
224              
225             my $err;
226             for (1 .. $max_tries) {
227             return (1) if unlink($file);
228             $err = "$!";
229             last if $_ == $max_tries;
230             sleep 1;
231             }
232              
233             return (0, "$!");
234             };
235             }
236             else {
237             *do_rename = sub {
238 37     37   162 my ($from, $to) = @_;
239 37 50       2183 return (1) if rename($from, $to);
240 0         0 return (0, "$!");
241 247         1610 };
242             *do_unlink = sub {
243 70     70   202 my ($file) = @_;
244 70 50       4334 return (1) if unlink($file);
245 0         0 return (0, "$!");
246 247         40943 };
247             }
248             }
249              
250             sub try_sig_mask(&) {
251 36     36 1 108 my $code = shift;
252              
253 36         124 my ($old, $blocked);
254 36         86 unless(IS_WIN32) {
255 36         819 my $to_block = POSIX::SigSet->new(
256             POSIX::SIGINT(),
257             POSIX::SIGALRM(),
258             POSIX::SIGHUP(),
259             POSIX::SIGTERM(),
260             POSIX::SIGUSR1(),
261             POSIX::SIGUSR2(),
262             );
263 36         215 $old = POSIX::SigSet->new;
264 36         1014 $blocked = POSIX::sigprocmask(POSIX::SIG_BLOCK(), $to_block, $old);
265             # Silently go on if we failed to log signals, not much we can do.
266             }
267              
268 36         396 my ($ok, $err) = &try($code);
269              
270             # If our block was successful we want to restore the old mask.
271 36 50       608 POSIX::sigprocmask(POSIX::SIG_SETMASK(), $old, POSIX::SigSet->new()) if defined $blocked;
272              
273 36         338 return ($ok, $err);
274             }
275              
276             1;
277              
278             __END__
279              
280             =pod
281              
282             =encoding UTF-8
283              
284             =head1 NAME
285              
286             Test2::Util - Tools used by Test2 and friends.
287              
288             =head1 DESCRIPTION
289              
290             Collection of tools used by L<Test2> and friends.
291              
292             =head1 EXPORTS
293              
294             All exports are optional. You must specify subs to import.
295              
296             =over 4
297              
298             =item ($success, $error) = try { ... }
299              
300             Eval the codeblock, return success or failure, and the error message. This code
301             protects $@ and $!, they will be restored by the end of the run. This code also
302             temporarily blocks $SIG{DIE} handlers.
303              
304             =item protect { ... }
305              
306             Similar to try, except that it does not catch exceptions. The idea here is to
307             protect $@ and $! from changes. $@ and $! will be restored to whatever they
308             were before the run so long as it is successful. If the run fails $! will still
309             be restored, but $@ will contain the exception being thrown.
310              
311             =item CAN_FORK
312              
313             True if this system is capable of true or pseudo-fork.
314              
315             =item CAN_REALLY_FORK
316              
317             True if the system can really fork. This will be false for systems where fork
318             is emulated.
319              
320             =item CAN_THREAD
321              
322             True if this system is capable of using threads.
323              
324             =item USE_THREADS
325              
326             Returns true if threads are enabled, false if they are not.
327              
328             =item get_tid
329              
330             This will return the id of the current thread when threads are enabled,
331             otherwise it returns 0.
332              
333             =item my $file = pkg_to_file($package)
334              
335             Convert a package name to a filename.
336              
337             =item $string = ipc_separator()
338              
339             Get the IPC separator. Currently this is always the string C<'~'>.
340              
341             =item $string = gen_uid()
342              
343             Generate a unique id (NOT A UUID). This will typically be the process id, the
344             thread id, the time, and an incrementing integer all joined with the
345             C<ipc_separator()>.
346              
347             These ID's are unique enough for most purposes. For identical ids to be
348             generated you must have 2 processes with the same PID generate IDs at the same
349             time with the same current state of the incrementing integer. This is a
350             perfectly reasonable thing to expect to happen across multiple machines, but is
351             quite unlikely to happen on one machine.
352              
353             This can fail to be unique if a process generates an id, calls exec, and does
354             it again after the exec and it all happens in less than a second. It can also
355             happen if the systems process id's cycle in less than a second allowing 2
356             different programs that use this generator to run with the same PID in less
357             than a second. Both these cases are sufficiently unlikely. If you need
358             universally unique ids, or ids that are unique in these conditions, look at
359             L<Data::UUID>.
360              
361             =item ($ok, $err) = do_rename($old_name, $new_name)
362              
363             Rename a file, this wraps C<rename()> in a way that makes it more reliable
364             cross-platform when trying to rename files you recently altered.
365              
366             =item ($ok, $err) = do_unlink($filename)
367              
368             Unlink a file, this wraps C<unlink()> in a way that makes it more reliable
369             cross-platform when trying to unlink files you recently altered.
370              
371             =item ($ok, $err) = try_sig_mask { ... }
372              
373             Complete an action with several signals masked, they will be unmasked at the
374             end allowing any signals that were intercepted to get handled.
375              
376             This is primarily used when you need to make several actions atomic (against
377             some signals anyway).
378              
379             Signals that are intercepted:
380              
381             =over 4
382              
383             =item SIGINT
384              
385             =item SIGALRM
386              
387             =item SIGHUP
388              
389             =item SIGTERM
390              
391             =item SIGUSR1
392              
393             =item SIGUSR2
394              
395             =back
396              
397             =back
398              
399             =head1 NOTES && CAVEATS
400              
401             =over 4
402              
403             =item 5.10.0
404              
405             Perl 5.10.0 has a bug when compiled with newer gcc versions. This bug causes a
406             segfault whenever a new thread is launched. Test2 will attempt to detect
407             this, and note that the system is not capable of forking when it is detected.
408              
409             =item Devel::Cover
410              
411             Devel::Cover does not support threads. CAN_THREAD will return false if
412             Devel::Cover is loaded before the check is first run.
413              
414             =back
415              
416             =head1 SOURCE
417              
418             The source code repository for Test2 can be found at
419             F<http://github.com/Test-More/test-more/>.
420              
421             =head1 MAINTAINERS
422              
423             =over 4
424              
425             =item Chad Granum E<lt>exodist@cpan.orgE<gt>
426              
427             =back
428              
429             =head1 AUTHORS
430              
431             =over 4
432              
433             =item Chad Granum E<lt>exodist@cpan.orgE<gt>
434              
435             =item Kent Fredric E<lt>kentnl@cpan.orgE<gt>
436              
437             =back
438              
439             =head1 COPYRIGHT
440              
441             Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
442              
443             This program is free software; you can redistribute it and/or
444             modify it under the same terms as Perl itself.
445              
446             See F<http://dev.perl.org/licenses/>
447              
448             =cut