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