This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Get t/uni/cache.t working under minitest
[perl5.git] / t / op / getppid.t
CommitLineData
098f0b12
RGS
1#!./perl
2
3# Test that getppid() follows UNIX semantics: when the parent process
a428795d
NC
4# dies, the child is reparented to the init process
5# The init process is usually 1, but doesn't have to be, and there's no
6# standard way to find out what it is, so the only portable way to go it so
7# attempt 2 reparentings and see if the PID both orphaned grandchildren get is
8# the same. (and not ours)
098f0b12
RGS
9
10BEGIN {
11 chdir 't' if -d 't';
12 @INC = qw(../lib);
13}
14
15use strict;
098f0b12
RGS
16
17BEGIN {
a428795d 18 require './test.pl';
77ba2250 19 skip_all_without_config(qw(d_pipe d_fork d_waitpid d_getppid));
bd5a473b 20 plan (8);
098f0b12
RGS
21}
22
e5325a77
NC
23# No, we don't want any zombies. kill 0, $ppid spots zombies :-(
24$SIG{CHLD} = 'IGNORE';
25
a428795d
NC
26sub fork_and_retrieve {
27 my $which = shift;
28 pipe my ($r, $w) or die "pipe: $!\n";
29 my $pid = fork; defined $pid or die "fork: $!\n";
098f0b12 30
a428795d
NC
31 if ($pid) {
32 # parent
a374d15c 33 close $w or die "close: $!\n";
a428795d
NC
34 $_ = <$r>;
35 chomp;
36 die "Garbled output '$_'"
e5325a77 37 unless my ($how, $first, $second) = /^([a-z]+),(\d+),(\d+)\z/;
a428795d 38 cmp_ok ($first, '>=', 1, "Parent of $which grandchild");
e5325a77
NC
39 my $message = "grandchild waited until '$how'";
40 cmp_ok ($second, '>=', 1, "New parent of orphaned $which grandchild")
41 ? note ($message) : diag ($message);
42
185a8799
MK
43 SKIP: {
44 skip("Orphan processes are not reparented on QNX", 1)
45 if $^O eq 'nto';
46 isnt($first, $second,
47 "Orphaned $which grandchild got a new parent");
48 }
a428795d 49 return $second;
098f0b12
RGS
50 }
51 else {
a428795d
NC
52 # child
53 # Prevent test.pl from thinking that we failed to run any tests.
54 $::NO_ENDING = 1;
a374d15c 55 close $r or die "close: $!\n";
a428795d 56
7285a48a
NC
57 pipe my ($r2, $w2) or die "pipe: $!\n";
58 pipe my ($r3, $w3) or die "pipe: $!\n";
a428795d
NC
59 my $pid2 = fork; defined $pid2 or die "fork: $!\n";
60 if ($pid2) {
a374d15c 61 close $w or die "close: $!\n";
7285a48a
NC
62 close $w2 or die "close: $!\n";
63 close $r3 or die "close: $!\n";
64 # Wait for our child to signal that it's read our PID:
65 <$r2>;
66 # Implicit close of $w3:
67 exit 0;
a428795d
NC
68 }
69 else {
70 # grandchild
7285a48a
NC
71 close $r2 or die "close: $!\n";
72 close $w3 or die "close: $!\n";
a428795d 73 my $ppid1 = getppid();
e5325a77
NC
74 # kill 0 isn't portable:
75 my $can_kill0 = eval {
76 kill 0, $ppid1;
77 };
78 my $how = $can_kill0 ? 'undead' : 'sleep';
79
7285a48a
NC
80 # Tell immediate parent to exit:
81 close $w2 or die "close: $!\n";
82 # Wait for it to (start to) exit:
83 <$r3>;
84 # Which sadly isn't enough to be sure that it has exited - often we
85 # get switched in during its shutdown, after $w3 closes but before
e5325a77
NC
86 # it exits and we get reparented.
87 if ($can_kill0) {
88 # use kill 0 where possible. Try 10 times, then give up:
89 for (0..9) {
90 my $got = kill 0, $ppid1;
91 die "kill: $!" unless defined $got;
92 if (!$got) {
93 $how = 'kill';
94 last;
95 }
96 sleep 1;
97 }
98 } else {
99 # Fudge it by waiting a bit more:
100 sleep 2;
101 }
a428795d 102 my $ppid2 = getppid();
e5325a77 103 print $w "$how,$ppid1,$ppid2\n";
a428795d
NC
104 }
105 exit 0;
098f0b12 106 }
098f0b12 107}
a428795d
NC
108
109my $first = fork_and_retrieve("first");
110my $second = fork_and_retrieve("second");
185a8799
MK
111SKIP: {
112 skip ("Orphan processes are not reparented on QNX", 1) if $^O eq 'nto';
113 is ($first, $second, "Both orphaned grandchildren get the same new parent");
114}
bd5a473b 115isnt ($first, $$, "And that new parent isn't this process");