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