1BEGIN { 2 use Config; 3 unless ($Config{d_fork}) { 4 print "1..0 # Skip: no fork\n"; 5 exit 0; 6 } 7 eval 'use POSIX qw(sys_wait_h)'; 8 if ($@) { 9 print "1..0 # Skip: no POSIX sys_wait_h\n"; 10 exit 0; 11 } 12 eval 'use Time::HiRes qw(time)'; 13 if ($@) { 14 print "1..0 # Skip: no Time::HiRes\n"; 15 exit 0; 16 } 17} 18 19use warnings; 20use strict; 21 22$| = 1; 23 24use Test::More tests => 3; 25 26sub NEG1_PROHIBITED () { 0x01 } 27sub NEG1_REQUIRED () { 0x02 } 28 29my $count = 0; 30my $max_count = 9; 31my $state = NEG1_PROHIBITED; 32 33my $child_pid = fork(); 34fail("fork failed") unless defined $child_pid; 35 36# Parent receives a nonzero child PID. 37 38if ($child_pid) { 39 my @problems; 40 41 while ($count++ < $max_count) { 42 my $begin_time = time(); 43 my $ret = waitpid( -1, WNOHANG ); 44 my $elapsed_time = time() - $begin_time; 45 46 printf( "# waitpid(-1,WNOHANG) returned %d after %.2f seconds\n", 47 $ret, $elapsed_time ); 48 if ($elapsed_time > 0.5) { 49 push @problems, 50 sprintf "%.2f seconds in non-blocking waitpid is too long!\n", 51 $elapsed_time; 52 last; 53 } 54 55 if ($state & NEG1_PROHIBITED) { 56 if ($ret == -1) { 57 push @problems, "waitpid should not have returned -1 here!\n"; 58 last; 59 } 60 elsif ($ret == $child_pid) { 61 $state = NEG1_REQUIRED; 62 is(WIFEXITED(${^CHILD_ERROR_NATIVE}), 1, 'child exited cleanly'); 63 is(WEXITSTATUS(${^CHILD_ERROR_NATIVE}), 0, 64 'child exited with 0 (the retun value of its sleep(3) call)'); 65 66 } 67 } 68 elsif ($state & NEG1_REQUIRED) { 69 unless ($ret == -1) { 70 push @problems, "waitpid should have returned -1 here!\n"; 71 } 72 last; 73 } 74 75 sleep(1); 76 } 77 is("@problems", "", 'no problems'); 78 POSIX::exit(0); # parent 79 fail("Should have exited"); 80} else { 81 # Child receives a zero PID and can request parent's PID with 82 # getppid(). 83 POSIX::_exit(POSIX::sleep(3)); 84} 85