xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/t/op/fork.t (revision 0:68f95e015346)
1*0Sstevel@tonic-gate#!./perl
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gate# tests for both real and emulated fork()
4*0Sstevel@tonic-gate
5*0Sstevel@tonic-gateBEGIN {
6*0Sstevel@tonic-gate    chdir 't' if -d 't';
7*0Sstevel@tonic-gate    @INC = '../lib';
8*0Sstevel@tonic-gate    require Config; import Config;
9*0Sstevel@tonic-gate    unless ($Config{'d_fork'}
10*0Sstevel@tonic-gate	    or (($^O eq 'MSWin32' || $^O eq 'NetWare') and $Config{useithreads}
11*0Sstevel@tonic-gate		and $Config{ccflags} =~ /-DPERL_IMPLICIT_SYS/
12*0Sstevel@tonic-gate#               and !defined $Config{'useperlio'}
13*0Sstevel@tonic-gate               ))
14*0Sstevel@tonic-gate    {
15*0Sstevel@tonic-gate	print "1..0 # Skip: no fork\n";
16*0Sstevel@tonic-gate	exit 0;
17*0Sstevel@tonic-gate    }
18*0Sstevel@tonic-gate    $ENV{PERL5LIB} = "../lib";
19*0Sstevel@tonic-gate}
20*0Sstevel@tonic-gate
21*0Sstevel@tonic-gateif ($^O eq 'mpeix') {
22*0Sstevel@tonic-gate    print "1..0 # Skip: fork/status problems on MPE/iX\n";
23*0Sstevel@tonic-gate    exit 0;
24*0Sstevel@tonic-gate}
25*0Sstevel@tonic-gate
26*0Sstevel@tonic-gate$|=1;
27*0Sstevel@tonic-gate
28*0Sstevel@tonic-gateundef $/;
29*0Sstevel@tonic-gate@prgs = split "\n########\n", <DATA>;
30*0Sstevel@tonic-gateprint "1..", scalar @prgs, "\n";
31*0Sstevel@tonic-gate
32*0Sstevel@tonic-gate$tmpfile = "forktmp000";
33*0Sstevel@tonic-gate1 while -f ++$tmpfile;
34*0Sstevel@tonic-gateEND { close TEST; unlink $tmpfile if $tmpfile; }
35*0Sstevel@tonic-gate
36*0Sstevel@tonic-gate$CAT = (($^O eq 'MSWin32') ? '.\perl -e "print <>"' : (($^O eq 'NetWare') ? 'perl -e "print <>"' : 'cat'));
37*0Sstevel@tonic-gate
38*0Sstevel@tonic-gatefor (@prgs){
39*0Sstevel@tonic-gate    my $switch;
40*0Sstevel@tonic-gate    if (s/^\s*(-\w.*)//){
41*0Sstevel@tonic-gate	$switch = $1;
42*0Sstevel@tonic-gate    }
43*0Sstevel@tonic-gate    my($prog,$expected) = split(/\nEXPECT\n/, $_);
44*0Sstevel@tonic-gate    $expected =~ s/\n+$//;
45*0Sstevel@tonic-gate    # results can be in any order, so sort 'em
46*0Sstevel@tonic-gate    my @expected = sort split /\n/, $expected;
47*0Sstevel@tonic-gate    open TEST, ">$tmpfile" or die "Cannot open $tmpfile: $!";
48*0Sstevel@tonic-gate    print TEST $prog, "\n";
49*0Sstevel@tonic-gate    close TEST or die "Cannot close $tmpfile: $!";
50*0Sstevel@tonic-gate    my $results;
51*0Sstevel@tonic-gate    if ($^O eq 'MSWin32') {
52*0Sstevel@tonic-gate      $results = `.\\perl -I../lib $switch $tmpfile 2>&1`;
53*0Sstevel@tonic-gate    }
54*0Sstevel@tonic-gate    elsif ($^O eq 'NetWare') {
55*0Sstevel@tonic-gate      $results = `perl -I../lib $switch $tmpfile 2>&1`;
56*0Sstevel@tonic-gate    }
57*0Sstevel@tonic-gate    else {
58*0Sstevel@tonic-gate      $results = `./perl $switch $tmpfile 2>&1`;
59*0Sstevel@tonic-gate    }
60*0Sstevel@tonic-gate    $status = $?;
61*0Sstevel@tonic-gate    $results =~ s/\n+$//;
62*0Sstevel@tonic-gate    $results =~ s/at\s+forktmp\d+\s+line/at - line/g;
63*0Sstevel@tonic-gate    $results =~ s/of\s+forktmp\d+\s+aborted/of - aborted/g;
64*0Sstevel@tonic-gate# bison says 'parse error' instead of 'syntax error',
65*0Sstevel@tonic-gate# various yaccs may or may not capitalize 'syntax'.
66*0Sstevel@tonic-gate    $results =~ s/^(syntax|parse) error/syntax error/mig;
67*0Sstevel@tonic-gate    $results =~ s/^\n*Process terminated by SIG\w+\n?//mg
68*0Sstevel@tonic-gate	if $^O eq 'os2';
69*0Sstevel@tonic-gate    my @results = sort split /\n/, $results;
70*0Sstevel@tonic-gate    if ( "@results" ne "@expected" ) {
71*0Sstevel@tonic-gate	print STDERR "PROG: $switch\n$prog\n";
72*0Sstevel@tonic-gate	print STDERR "EXPECTED:\n$expected\n";
73*0Sstevel@tonic-gate	print STDERR "GOT:\n$results\n";
74*0Sstevel@tonic-gate	print "not ";
75*0Sstevel@tonic-gate    }
76*0Sstevel@tonic-gate    print "ok ", ++$i, "\n";
77*0Sstevel@tonic-gate}
78*0Sstevel@tonic-gate
79*0Sstevel@tonic-gate__END__
80*0Sstevel@tonic-gate$| = 1;
81*0Sstevel@tonic-gateif ($cid = fork) {
82*0Sstevel@tonic-gate    sleep 1;
83*0Sstevel@tonic-gate    if ($result = (kill 9, $cid)) {
84*0Sstevel@tonic-gate	print "ok 2\n";
85*0Sstevel@tonic-gate    }
86*0Sstevel@tonic-gate    else {
87*0Sstevel@tonic-gate	print "not ok 2 $result\n";
88*0Sstevel@tonic-gate    }
89*0Sstevel@tonic-gate    sleep 1 if $^O eq 'MSWin32';	# avoid WinNT race bug
90*0Sstevel@tonic-gate}
91*0Sstevel@tonic-gateelse {
92*0Sstevel@tonic-gate    print "ok 1\n";
93*0Sstevel@tonic-gate    sleep 10;
94*0Sstevel@tonic-gate}
95*0Sstevel@tonic-gateEXPECT
96*0Sstevel@tonic-gateok 1
97*0Sstevel@tonic-gateok 2
98*0Sstevel@tonic-gate########
99*0Sstevel@tonic-gate$| = 1;
100*0Sstevel@tonic-gatesub forkit {
101*0Sstevel@tonic-gate    print "iteration $i start\n";
102*0Sstevel@tonic-gate    my $x = fork;
103*0Sstevel@tonic-gate    if (defined $x) {
104*0Sstevel@tonic-gate	if ($x) {
105*0Sstevel@tonic-gate	    print "iteration $i parent\n";
106*0Sstevel@tonic-gate	}
107*0Sstevel@tonic-gate	else {
108*0Sstevel@tonic-gate	    print "iteration $i child\n";
109*0Sstevel@tonic-gate	}
110*0Sstevel@tonic-gate    }
111*0Sstevel@tonic-gate    else {
112*0Sstevel@tonic-gate	print "pid $$ failed to fork\n";
113*0Sstevel@tonic-gate    }
114*0Sstevel@tonic-gate}
115*0Sstevel@tonic-gatewhile ($i++ < 3) { do { forkit(); }; }
116*0Sstevel@tonic-gateEXPECT
117*0Sstevel@tonic-gateiteration 1 start
118*0Sstevel@tonic-gateiteration 1 parent
119*0Sstevel@tonic-gateiteration 1 child
120*0Sstevel@tonic-gateiteration 2 start
121*0Sstevel@tonic-gateiteration 2 parent
122*0Sstevel@tonic-gateiteration 2 child
123*0Sstevel@tonic-gateiteration 2 start
124*0Sstevel@tonic-gateiteration 2 parent
125*0Sstevel@tonic-gateiteration 2 child
126*0Sstevel@tonic-gateiteration 3 start
127*0Sstevel@tonic-gateiteration 3 parent
128*0Sstevel@tonic-gateiteration 3 child
129*0Sstevel@tonic-gateiteration 3 start
130*0Sstevel@tonic-gateiteration 3 parent
131*0Sstevel@tonic-gateiteration 3 child
132*0Sstevel@tonic-gateiteration 3 start
133*0Sstevel@tonic-gateiteration 3 parent
134*0Sstevel@tonic-gateiteration 3 child
135*0Sstevel@tonic-gateiteration 3 start
136*0Sstevel@tonic-gateiteration 3 parent
137*0Sstevel@tonic-gateiteration 3 child
138*0Sstevel@tonic-gate########
139*0Sstevel@tonic-gate$| = 1;
140*0Sstevel@tonic-gatefork()
141*0Sstevel@tonic-gate ? (print("parent\n"),sleep(1))
142*0Sstevel@tonic-gate : (print("child\n"),exit) ;
143*0Sstevel@tonic-gateEXPECT
144*0Sstevel@tonic-gateparent
145*0Sstevel@tonic-gatechild
146*0Sstevel@tonic-gate########
147*0Sstevel@tonic-gate$| = 1;
148*0Sstevel@tonic-gatefork()
149*0Sstevel@tonic-gate ? (print("parent\n"),exit)
150*0Sstevel@tonic-gate : (print("child\n"),sleep(1)) ;
151*0Sstevel@tonic-gateEXPECT
152*0Sstevel@tonic-gateparent
153*0Sstevel@tonic-gatechild
154*0Sstevel@tonic-gate########
155*0Sstevel@tonic-gate$| = 1;
156*0Sstevel@tonic-gate@a = (1..3);
157*0Sstevel@tonic-gatefor (@a) {
158*0Sstevel@tonic-gate    if (fork) {
159*0Sstevel@tonic-gate	print "parent $_\n";
160*0Sstevel@tonic-gate	$_ = "[$_]";
161*0Sstevel@tonic-gate    }
162*0Sstevel@tonic-gate    else {
163*0Sstevel@tonic-gate	print "child $_\n";
164*0Sstevel@tonic-gate	$_ = "-$_-";
165*0Sstevel@tonic-gate    }
166*0Sstevel@tonic-gate}
167*0Sstevel@tonic-gateprint "@a\n";
168*0Sstevel@tonic-gateEXPECT
169*0Sstevel@tonic-gateparent 1
170*0Sstevel@tonic-gatechild 1
171*0Sstevel@tonic-gateparent 2
172*0Sstevel@tonic-gatechild 2
173*0Sstevel@tonic-gateparent 2
174*0Sstevel@tonic-gatechild 2
175*0Sstevel@tonic-gateparent 3
176*0Sstevel@tonic-gatechild 3
177*0Sstevel@tonic-gateparent 3
178*0Sstevel@tonic-gatechild 3
179*0Sstevel@tonic-gateparent 3
180*0Sstevel@tonic-gatechild 3
181*0Sstevel@tonic-gateparent 3
182*0Sstevel@tonic-gatechild 3
183*0Sstevel@tonic-gate[1] [2] [3]
184*0Sstevel@tonic-gate-1- [2] [3]
185*0Sstevel@tonic-gate[1] -2- [3]
186*0Sstevel@tonic-gate[1] [2] -3-
187*0Sstevel@tonic-gate-1- -2- [3]
188*0Sstevel@tonic-gate-1- [2] -3-
189*0Sstevel@tonic-gate[1] -2- -3-
190*0Sstevel@tonic-gate-1- -2- -3-
191*0Sstevel@tonic-gate########
192*0Sstevel@tonic-gate$| = 1;
193*0Sstevel@tonic-gateforeach my $c (1,2,3) {
194*0Sstevel@tonic-gate    if (fork) {
195*0Sstevel@tonic-gate	print "parent $c\n";
196*0Sstevel@tonic-gate    }
197*0Sstevel@tonic-gate    else {
198*0Sstevel@tonic-gate	print "child $c\n";
199*0Sstevel@tonic-gate	exit;
200*0Sstevel@tonic-gate    }
201*0Sstevel@tonic-gate}
202*0Sstevel@tonic-gatewhile (wait() != -1) { print "waited\n" }
203*0Sstevel@tonic-gateEXPECT
204*0Sstevel@tonic-gatechild 1
205*0Sstevel@tonic-gatechild 2
206*0Sstevel@tonic-gatechild 3
207*0Sstevel@tonic-gateparent 1
208*0Sstevel@tonic-gateparent 2
209*0Sstevel@tonic-gateparent 3
210*0Sstevel@tonic-gatewaited
211*0Sstevel@tonic-gatewaited
212*0Sstevel@tonic-gatewaited
213*0Sstevel@tonic-gate########
214*0Sstevel@tonic-gateuse Config;
215*0Sstevel@tonic-gate$| = 1;
216*0Sstevel@tonic-gate$\ = "\n";
217*0Sstevel@tonic-gatefork()
218*0Sstevel@tonic-gate ? print($Config{osname} eq $^O)
219*0Sstevel@tonic-gate : print($Config{osname} eq $^O) ;
220*0Sstevel@tonic-gateEXPECT
221*0Sstevel@tonic-gate1
222*0Sstevel@tonic-gate1
223*0Sstevel@tonic-gate########
224*0Sstevel@tonic-gate$| = 1;
225*0Sstevel@tonic-gate$\ = "\n";
226*0Sstevel@tonic-gatefork()
227*0Sstevel@tonic-gate ? do { require Config; print($Config::Config{osname} eq $^O); }
228*0Sstevel@tonic-gate : do { require Config; print($Config::Config{osname} eq $^O); }
229*0Sstevel@tonic-gateEXPECT
230*0Sstevel@tonic-gate1
231*0Sstevel@tonic-gate1
232*0Sstevel@tonic-gate########
233*0Sstevel@tonic-gate$| = 1;
234*0Sstevel@tonic-gateuse Cwd;
235*0Sstevel@tonic-gate$\ = "\n";
236*0Sstevel@tonic-gatemy $dir;
237*0Sstevel@tonic-gateif (fork) {
238*0Sstevel@tonic-gate    $dir = "f$$.tst";
239*0Sstevel@tonic-gate    mkdir $dir, 0755;
240*0Sstevel@tonic-gate    chdir $dir;
241*0Sstevel@tonic-gate    print cwd() =~ /\Q$dir/i ? "ok 1 parent" : "not ok 1 parent";
242*0Sstevel@tonic-gate    chdir "..";
243*0Sstevel@tonic-gate    rmdir $dir;
244*0Sstevel@tonic-gate}
245*0Sstevel@tonic-gateelse {
246*0Sstevel@tonic-gate    sleep 2;
247*0Sstevel@tonic-gate    $dir = "f$$.tst";
248*0Sstevel@tonic-gate    mkdir $dir, 0755;
249*0Sstevel@tonic-gate    chdir $dir;
250*0Sstevel@tonic-gate    print cwd() =~ /\Q$dir/i ? "ok 1 child" : "not ok 1 child";
251*0Sstevel@tonic-gate    chdir "..";
252*0Sstevel@tonic-gate    rmdir $dir;
253*0Sstevel@tonic-gate}
254*0Sstevel@tonic-gateEXPECT
255*0Sstevel@tonic-gateok 1 parent
256*0Sstevel@tonic-gateok 1 child
257*0Sstevel@tonic-gate########
258*0Sstevel@tonic-gate$| = 1;
259*0Sstevel@tonic-gate$\ = "\n";
260*0Sstevel@tonic-gatemy $getenv;
261*0Sstevel@tonic-gateif ($^O eq 'MSWin32' || $^O eq 'NetWare') {
262*0Sstevel@tonic-gate    $getenv = qq[$^X -e "print \$ENV{TST}"];
263*0Sstevel@tonic-gate}
264*0Sstevel@tonic-gateelse {
265*0Sstevel@tonic-gate    $getenv = qq[$^X -e 'print \$ENV{TST}'];
266*0Sstevel@tonic-gate}
267*0Sstevel@tonic-gate$ENV{TST} = 'foo';
268*0Sstevel@tonic-gateif (fork) {
269*0Sstevel@tonic-gate    sleep 1;
270*0Sstevel@tonic-gate    print "parent before: " . `$getenv`;
271*0Sstevel@tonic-gate    $ENV{TST} = 'bar';
272*0Sstevel@tonic-gate    print "parent after: " . `$getenv`;
273*0Sstevel@tonic-gate}
274*0Sstevel@tonic-gateelse {
275*0Sstevel@tonic-gate    print "child before: " . `$getenv`;
276*0Sstevel@tonic-gate    $ENV{TST} = 'baz';
277*0Sstevel@tonic-gate    print "child after: " . `$getenv`;
278*0Sstevel@tonic-gate}
279*0Sstevel@tonic-gateEXPECT
280*0Sstevel@tonic-gatechild before: foo
281*0Sstevel@tonic-gatechild after: baz
282*0Sstevel@tonic-gateparent before: foo
283*0Sstevel@tonic-gateparent after: bar
284*0Sstevel@tonic-gate########
285*0Sstevel@tonic-gate$| = 1;
286*0Sstevel@tonic-gate$\ = "\n";
287*0Sstevel@tonic-gateif ($pid = fork) {
288*0Sstevel@tonic-gate    waitpid($pid,0);
289*0Sstevel@tonic-gate    print "parent got $?"
290*0Sstevel@tonic-gate}
291*0Sstevel@tonic-gateelse {
292*0Sstevel@tonic-gate    exit(42);
293*0Sstevel@tonic-gate}
294*0Sstevel@tonic-gateEXPECT
295*0Sstevel@tonic-gateparent got 10752
296*0Sstevel@tonic-gate########
297*0Sstevel@tonic-gate$| = 1;
298*0Sstevel@tonic-gate$\ = "\n";
299*0Sstevel@tonic-gatemy $echo = 'echo';
300*0Sstevel@tonic-gateif ($pid = fork) {
301*0Sstevel@tonic-gate    waitpid($pid,0);
302*0Sstevel@tonic-gate    print "parent got $?"
303*0Sstevel@tonic-gate}
304*0Sstevel@tonic-gateelse {
305*0Sstevel@tonic-gate    exec("$echo foo");
306*0Sstevel@tonic-gate}
307*0Sstevel@tonic-gateEXPECT
308*0Sstevel@tonic-gatefoo
309*0Sstevel@tonic-gateparent got 0
310*0Sstevel@tonic-gate########
311*0Sstevel@tonic-gateif (fork) {
312*0Sstevel@tonic-gate    die "parent died";
313*0Sstevel@tonic-gate}
314*0Sstevel@tonic-gateelse {
315*0Sstevel@tonic-gate    die "child died";
316*0Sstevel@tonic-gate}
317*0Sstevel@tonic-gateEXPECT
318*0Sstevel@tonic-gateparent died at - line 2.
319*0Sstevel@tonic-gatechild died at - line 5.
320*0Sstevel@tonic-gate########
321*0Sstevel@tonic-gateif ($pid = fork) {
322*0Sstevel@tonic-gate    eval { die "parent died" };
323*0Sstevel@tonic-gate    print $@;
324*0Sstevel@tonic-gate}
325*0Sstevel@tonic-gateelse {
326*0Sstevel@tonic-gate    eval { die "child died" };
327*0Sstevel@tonic-gate    print $@;
328*0Sstevel@tonic-gate}
329*0Sstevel@tonic-gateEXPECT
330*0Sstevel@tonic-gateparent died at - line 2.
331*0Sstevel@tonic-gatechild died at - line 6.
332*0Sstevel@tonic-gate########
333*0Sstevel@tonic-gateif (eval q{$pid = fork}) {
334*0Sstevel@tonic-gate    eval q{ die "parent died" };
335*0Sstevel@tonic-gate    print $@;
336*0Sstevel@tonic-gate}
337*0Sstevel@tonic-gateelse {
338*0Sstevel@tonic-gate    eval q{ die "child died" };
339*0Sstevel@tonic-gate    print $@;
340*0Sstevel@tonic-gate}
341*0Sstevel@tonic-gateEXPECT
342*0Sstevel@tonic-gateparent died at (eval 2) line 1.
343*0Sstevel@tonic-gatechild died at (eval 2) line 1.
344*0Sstevel@tonic-gate########
345*0Sstevel@tonic-gateBEGIN {
346*0Sstevel@tonic-gate    $| = 1;
347*0Sstevel@tonic-gate    fork and exit;
348*0Sstevel@tonic-gate    print "inner\n";
349*0Sstevel@tonic-gate}
350*0Sstevel@tonic-gate# XXX In emulated fork(), the child will not execute anything after
351*0Sstevel@tonic-gate# the BEGIN block, due to difficulties in recreating the parse stacks
352*0Sstevel@tonic-gate# and restarting yyparse() midstream in the child.  This can potentially
353*0Sstevel@tonic-gate# be overcome by treating what's after the BEGIN{} as a brand new parse.
354*0Sstevel@tonic-gate#print "outer\n"
355*0Sstevel@tonic-gateEXPECT
356*0Sstevel@tonic-gateinner
357*0Sstevel@tonic-gate########
358*0Sstevel@tonic-gatesub pipe_to_fork ($$) {
359*0Sstevel@tonic-gate    my $parent = shift;
360*0Sstevel@tonic-gate    my $child = shift;
361*0Sstevel@tonic-gate    pipe($child, $parent) or die;
362*0Sstevel@tonic-gate    my $pid = fork();
363*0Sstevel@tonic-gate    die "fork() failed: $!" unless defined $pid;
364*0Sstevel@tonic-gate    close($pid ? $child : $parent);
365*0Sstevel@tonic-gate    $pid;
366*0Sstevel@tonic-gate}
367*0Sstevel@tonic-gate
368*0Sstevel@tonic-gateif (pipe_to_fork('PARENT','CHILD')) {
369*0Sstevel@tonic-gate    # parent
370*0Sstevel@tonic-gate    print PARENT "pipe_to_fork\n";
371*0Sstevel@tonic-gate    close PARENT;
372*0Sstevel@tonic-gate}
373*0Sstevel@tonic-gateelse {
374*0Sstevel@tonic-gate    # child
375*0Sstevel@tonic-gate    while (<CHILD>) { print; }
376*0Sstevel@tonic-gate    close CHILD;
377*0Sstevel@tonic-gate    exit;
378*0Sstevel@tonic-gate}
379*0Sstevel@tonic-gate
380*0Sstevel@tonic-gatesub pipe_from_fork ($$) {
381*0Sstevel@tonic-gate    my $parent = shift;
382*0Sstevel@tonic-gate    my $child = shift;
383*0Sstevel@tonic-gate    pipe($parent, $child) or die;
384*0Sstevel@tonic-gate    my $pid = fork();
385*0Sstevel@tonic-gate    die "fork() failed: $!" unless defined $pid;
386*0Sstevel@tonic-gate    close($pid ? $child : $parent);
387*0Sstevel@tonic-gate    $pid;
388*0Sstevel@tonic-gate}
389*0Sstevel@tonic-gate
390*0Sstevel@tonic-gateif (pipe_from_fork('PARENT','CHILD')) {
391*0Sstevel@tonic-gate    # parent
392*0Sstevel@tonic-gate    while (<PARENT>) { print; }
393*0Sstevel@tonic-gate    close PARENT;
394*0Sstevel@tonic-gate}
395*0Sstevel@tonic-gateelse {
396*0Sstevel@tonic-gate    # child
397*0Sstevel@tonic-gate    print CHILD "pipe_from_fork\n";
398*0Sstevel@tonic-gate    close CHILD;
399*0Sstevel@tonic-gate    exit;
400*0Sstevel@tonic-gate}
401*0Sstevel@tonic-gateEXPECT
402*0Sstevel@tonic-gatepipe_from_fork
403*0Sstevel@tonic-gatepipe_to_fork
404*0Sstevel@tonic-gate########
405*0Sstevel@tonic-gate$|=1;
406*0Sstevel@tonic-gateif ($pid = fork()) {
407*0Sstevel@tonic-gate    print "forked first kid\n";
408*0Sstevel@tonic-gate    print "waitpid() returned ok\n" if waitpid($pid,0) == $pid;
409*0Sstevel@tonic-gate}
410*0Sstevel@tonic-gateelse {
411*0Sstevel@tonic-gate    print "first child\n";
412*0Sstevel@tonic-gate    exit(0);
413*0Sstevel@tonic-gate}
414*0Sstevel@tonic-gateif ($pid = fork()) {
415*0Sstevel@tonic-gate    print "forked second kid\n";
416*0Sstevel@tonic-gate    print "wait() returned ok\n" if wait() == $pid;
417*0Sstevel@tonic-gate}
418*0Sstevel@tonic-gateelse {
419*0Sstevel@tonic-gate    print "second child\n";
420*0Sstevel@tonic-gate    exit(0);
421*0Sstevel@tonic-gate}
422*0Sstevel@tonic-gateEXPECT
423*0Sstevel@tonic-gateforked first kid
424*0Sstevel@tonic-gatefirst child
425*0Sstevel@tonic-gatewaitpid() returned ok
426*0Sstevel@tonic-gateforked second kid
427*0Sstevel@tonic-gatesecond child
428*0Sstevel@tonic-gatewait() returned ok
429*0Sstevel@tonic-gate########
430*0Sstevel@tonic-gatepipe(RDR,WTR) or die $!;
431*0Sstevel@tonic-gatemy $pid = fork;
432*0Sstevel@tonic-gatedie "fork: $!" if !defined $pid;
433*0Sstevel@tonic-gateif ($pid == 0) {
434*0Sstevel@tonic-gate    my $rand_child = rand;
435*0Sstevel@tonic-gate    close RDR;
436*0Sstevel@tonic-gate    print WTR $rand_child, "\n";
437*0Sstevel@tonic-gate    close WTR;
438*0Sstevel@tonic-gate} else {
439*0Sstevel@tonic-gate    my $rand_parent = rand;
440*0Sstevel@tonic-gate    close WTR;
441*0Sstevel@tonic-gate    chomp(my $rand_child  = <RDR>);
442*0Sstevel@tonic-gate    close RDR;
443*0Sstevel@tonic-gate    print $rand_child ne $rand_parent, "\n";
444*0Sstevel@tonic-gate}
445*0Sstevel@tonic-gateEXPECT
446*0Sstevel@tonic-gate1
447