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   13666 use strict;
  247         585  
  247         7096  
3 247     247   1329 use warnings;
  247         436  
  247         9366  
4              
5             our $VERSION = '1.302182';
6              
7 247     247   124282 use POSIX();
  247         1983601  
  247         8185  
8 247     247   1752 use Config qw/%Config/;
  247         486  
  247         12393  
9 247     247   1509 use Carp qw/croak/;
  247         458  
  247         26827  
10              
11             BEGIN {
12 247     247   2756 local ($@, $!, $SIG{__DIE__});
13 247 50       697 *HAVE_PERLIO = eval { require PerlIO; PerlIO->VERSION(1.02); } ? sub() { 1 } : sub() { 0 };
  247         148800  
  247         27445  
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   1623 BEGIN { require Exporter; our @ISA = qw(Exporter) }
  247         18064  
41              
42             BEGIN {
43 247 50   247   56714 *IS_WIN32 = ($^O eq 'MSWin32') ? sub() { 1 } : sub() { 0 };
44             }
45              
46             sub _can_thread {
47 247 50   247   1386 return 0 unless $] >= 5.008001;
48 247 50       21000 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   1897 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   1976 no warnings 'once';
  247         632  
  247         20998  
72 247 50   247   1056 *CAN_THREAD = _can_thread() ? sub() { 1 } : sub() { 0 };
73             }
74             my $can_fork;
75             sub CAN_FORK () {
76 39 100   39 1 1535 return $can_fork
77             if defined $can_fork;
78 27         252 $can_fork = !!_can_fork();
79 247     247   1834 no warnings 'redefine';
  247         535  
  247         30940  
80 27 50       692 *CAN_FORK = $can_fork ? sub() { 1 } : sub() { 0 };
81 27         178 $can_fork;
82             }
83             my $can_really_fork;
84             sub CAN_REALLY_FORK () {
85 24 100   24 1 239 return $can_really_fork
86             if defined $can_really_fork;
87 17         956 $can_really_fork = !!$Config{d_fork};
88 247     247   1797 no warnings 'redefine';
  247         516  
  247         58251  
89 17 50       161 *CAN_REALLY_FORK = $can_really_fork ? sub() { 1 } : sub() { 0 };
90 17         52 $can_really_fork;
91             }
92              
93             sub _manual_try(&;@) {
94 2     2   23 my $code = shift;
95 2         6 my $args = \@_;
96 2         3 my $err;
97              
98 2         10 my $die = delete $SIG{__DIE__};
99              
100 2 100 50     4 eval { $code->(@$args); 1 } or $err = $@ || "Error was squashed!\n";
  2         8  
  1         4  
101              
102 2 50       19 $die ? $SIG{__DIE__} = $die : delete $SIG{__DIE__};
103              
104 2         10 return (!defined($err), $err);
105             }
106              
107             sub _local_try(&;@) {
108 218     218   3878 my $code = shift;
109 218         548 my $args = \@_;
110 218         380 my $err;
111              
112 247     247   1779 no warnings;
  247         525  
  247         38142  
113 218         1146 local $SIG{__DIE__};
114 218 100 50     496 eval { $code->(@$args); 1 } or $err = $@ || "Error was squashed!\n";
  218         748  
  207         1122  
115              
116 218         2481 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   2051 if (IS_WIN32 && $] < 5.020002) {
124             *try = \&_manual_try;
125             }
126             else {
127 247         48500 *try = \&_local_try;
128             }
129             }
130              
131             BEGIN {
132 247     247   898 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         674 *USE_THREADS = sub() { 0 };
148 247         66091 *get_tid = sub() { 0 };
149             }
150             }
151              
152             sub pkg_to_file {
153 844     844 1 1360 my $pkg = shift;
154 844         1240 my $file = $pkg;
155 844         5053 $file =~ s{(::|')}{/}g;
156 844         1608 $file .= '.pm';
157 844         2156 return $file;
158             }
159              
160             sub ipc_separator() { "~" }
161              
162             my $UID = 1;
163 15120     15120 1 150571 sub gen_uid() { join ipc_separator() => ($$, get_tid(), time, $UID++) }
164              
165             sub _check_for_sig_sys {
166 252     252   25580 my $sig_list = shift;
167 252         2431 return $sig_list =~ m/\bSYS\b/;
168             }
169              
170             BEGIN {
171 247 50   247   1710 if (_check_for_sig_sys($Config{sig_name})) {
172 247         142383 *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 4304 my ($fh) = @_;
186 1200         2972 my $fileno = eval { fileno($fh) };
  1200         3978  
187              
188 1200 100 33     10221 return $fh if !defined($fileno) || !length($fileno) || $fileno < 0;
      66        
189              
190 1199 50       35487 open(my $out, '>&' . $fileno) or die "Can't dup fileno $fileno: $!";
191              
192 1199         3674 my %seen;
193 1199   100     9783 my @layers = HAVE_PERLIO ? grep { !$PERLIO_SKIP{$_} and !$seen{$_}++ } PerlIO::get_layers($fh) : ();
  3112         18672  
194 1199         13750 binmode($out, join(":", "", "raw", @layers));
195              
196 1199         6294 my $old = select $fh;
197 1199         3728 my $af = $|;
198 1199         2730 select $out;
199 1199         2731 $| = $af;
200 1199         3221 select $old;
201              
202 1199         5112 return $out;
203             }
204              
205             BEGIN {
206 247     247   1136 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   151 my ($from, $to) = @_;
239 37 50       2270 return (1) if rename($from, $to);
240 0         0 return (0, "$!");
241 247         1658 };
242             *do_unlink = sub {
243 70     70   190 my ($file) = @_;
244 70 50       4438 return (1) if unlink($file);
245 0         0 return (0, "$!");
246 247         41676 };
247             }
248             }
249              
250             sub try_sig_mask(&) {
251 36     36 1 174 my $code = shift;
252              
253 36         147 my ($old, $blocked);
254 36         115 unless(IS_WIN32) {
255 36         866 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         210 $old = POSIX::SigSet->new;
264 36         965 $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         447 my ($ok, $err) = &try($code);
269              
270             # If our block was successful we want to restore the old mask.
271 36 50       688 POSIX::sigprocmask(POSIX::SIG_SETMASK(), $old, POSIX::SigSet->new()) if defined $blocked;
272              
273 36         259 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