Commit | Line | Data |
---|---|---|
8d063cd8 LW |
1 | #!./perl |
2 | ||
7766f137 | 3 | # tests for both real and emulated fork() |
8d063cd8 | 4 | |
774d564b | 5 | BEGIN { |
6 | chdir 't' if -d 't'; | |
20822f61 | 7 | @INC = '../lib'; |
1c25d394 | 8 | require './test.pl'; |
95e2dc41 NC |
9 | require Config; |
10 | skip_all('no fork') | |
11 | unless ($Config::Config{d_fork} or $Config::Config{d_pseudofork}); | |
774d564b | 12 | } |
13 | ||
95e2dc41 NC |
14 | skip_all('fork/status problems on MPE/iX') |
15 | if $^O eq 'mpeix'; | |
0994c4d0 | 16 | |
7766f137 GS |
17 | $|=1; |
18 | ||
5f7e0818 | 19 | run_multiple_progs('', \*DATA); |
7766f137 | 20 | |
5f7e0818 | 21 | done_testing(); |
7766f137 GS |
22 | |
23 | __END__ | |
24 | $| = 1; | |
8d063cd8 | 25 | if ($cid = fork) { |
7766f137 GS |
26 | sleep 1; |
27 | if ($result = (kill 9, $cid)) { | |
28 | print "ok 2\n"; | |
29 | } | |
30 | else { | |
31 | print "not ok 2 $result\n"; | |
32 | } | |
33 | sleep 1 if $^O eq 'MSWin32'; # avoid WinNT race bug | |
8d063cd8 LW |
34 | } |
35 | else { | |
8d063cd8 LW |
36 | print "ok 1\n"; |
37 | sleep 10; | |
38 | } | |
7766f137 | 39 | EXPECT |
5f7e0818 | 40 | OPTION random |
7766f137 GS |
41 | ok 1 |
42 | ok 2 | |
43 | ######## | |
44 | $| = 1; | |
aeecf691 JD |
45 | if ($cid = fork) { |
46 | sleep 1; | |
47 | print "not " unless kill 'INT', $cid; | |
48 | print "ok 2\n"; | |
49 | } | |
50 | else { | |
51 | # XXX On Windows the default signal handler kills the | |
52 | # XXX whole process, not just the thread (pseudo-process) | |
53 | $SIG{INT} = sub { exit }; | |
54 | print "ok 1\n"; | |
55 | sleep 5; | |
56 | die; | |
57 | } | |
58 | EXPECT | |
5f7e0818 | 59 | OPTION random |
aeecf691 JD |
60 | ok 1 |
61 | ok 2 | |
62 | ######## | |
63 | $| = 1; | |
7766f137 GS |
64 | sub forkit { |
65 | print "iteration $i start\n"; | |
66 | my $x = fork; | |
67 | if (defined $x) { | |
68 | if ($x) { | |
69 | print "iteration $i parent\n"; | |
70 | } | |
71 | else { | |
72 | print "iteration $i child\n"; | |
73 | } | |
74 | } | |
75 | else { | |
76 | print "pid $$ failed to fork\n"; | |
77 | } | |
78 | } | |
79 | while ($i++ < 3) { do { forkit(); }; } | |
80 | EXPECT | |
5f7e0818 | 81 | OPTION random |
7766f137 GS |
82 | iteration 1 start |
83 | iteration 1 parent | |
84 | iteration 1 child | |
85 | iteration 2 start | |
86 | iteration 2 parent | |
87 | iteration 2 child | |
88 | iteration 2 start | |
89 | iteration 2 parent | |
90 | iteration 2 child | |
91 | iteration 3 start | |
92 | iteration 3 parent | |
93 | iteration 3 child | |
94 | iteration 3 start | |
95 | iteration 3 parent | |
96 | iteration 3 child | |
97 | iteration 3 start | |
98 | iteration 3 parent | |
99 | iteration 3 child | |
100 | iteration 3 start | |
101 | iteration 3 parent | |
102 | iteration 3 child | |
103 | ######## | |
104 | $| = 1; | |
105 | fork() | |
106 | ? (print("parent\n"),sleep(1)) | |
107 | : (print("child\n"),exit) ; | |
108 | EXPECT | |
5f7e0818 | 109 | OPTION random |
7766f137 GS |
110 | parent |
111 | child | |
112 | ######## | |
113 | $| = 1; | |
114 | fork() | |
115 | ? (print("parent\n"),exit) | |
116 | : (print("child\n"),sleep(1)) ; | |
117 | EXPECT | |
5f7e0818 | 118 | OPTION random |
7766f137 GS |
119 | parent |
120 | child | |
121 | ######## | |
122 | $| = 1; | |
123 | @a = (1..3); | |
124 | for (@a) { | |
125 | if (fork) { | |
126 | print "parent $_\n"; | |
127 | $_ = "[$_]"; | |
128 | } | |
129 | else { | |
130 | print "child $_\n"; | |
131 | $_ = "-$_-"; | |
132 | } | |
133 | } | |
134 | print "@a\n"; | |
135 | EXPECT | |
5f7e0818 | 136 | OPTION random |
7766f137 GS |
137 | parent 1 |
138 | child 1 | |
139 | parent 2 | |
140 | child 2 | |
141 | parent 2 | |
142 | child 2 | |
143 | parent 3 | |
144 | child 3 | |
145 | parent 3 | |
146 | child 3 | |
147 | parent 3 | |
148 | child 3 | |
149 | parent 3 | |
150 | child 3 | |
151 | [1] [2] [3] | |
152 | -1- [2] [3] | |
153 | [1] -2- [3] | |
154 | [1] [2] -3- | |
155 | -1- -2- [3] | |
156 | -1- [2] -3- | |
157 | [1] -2- -3- | |
158 | -1- -2- -3- | |
159 | ######## | |
c3564e5c GS |
160 | $| = 1; |
161 | foreach my $c (1,2,3) { | |
162 | if (fork) { | |
163 | print "parent $c\n"; | |
164 | } | |
165 | else { | |
166 | print "child $c\n"; | |
167 | exit; | |
168 | } | |
169 | } | |
170 | while (wait() != -1) { print "waited\n" } | |
171 | EXPECT | |
5f7e0818 | 172 | OPTION random |
c3564e5c GS |
173 | child 1 |
174 | child 2 | |
175 | child 3 | |
176 | parent 1 | |
177 | parent 2 | |
178 | parent 3 | |
179 | waited | |
180 | waited | |
181 | waited | |
182 | ######## | |
7766f137 GS |
183 | use Config; |
184 | $| = 1; | |
185 | $\ = "\n"; | |
186 | fork() | |
187 | ? print($Config{osname} eq $^O) | |
188 | : print($Config{osname} eq $^O) ; | |
189 | EXPECT | |
5f7e0818 | 190 | OPTION random |
7766f137 GS |
191 | 1 |
192 | 1 | |
193 | ######## | |
194 | $| = 1; | |
195 | $\ = "\n"; | |
196 | fork() | |
197 | ? do { require Config; print($Config::Config{osname} eq $^O); } | |
198 | : do { require Config; print($Config::Config{osname} eq $^O); } | |
199 | EXPECT | |
5f7e0818 | 200 | OPTION random |
7766f137 GS |
201 | 1 |
202 | 1 | |
203 | ######## | |
204 | $| = 1; | |
205 | use Cwd; | |
cf2f24a4 | 206 | my $cwd = cwd(); # Make sure we load Win32.pm while "../lib" still works. |
7766f137 GS |
207 | $\ = "\n"; |
208 | my $dir; | |
209 | if (fork) { | |
210 | $dir = "f$$.tst"; | |
211 | mkdir $dir, 0755; | |
212 | chdir $dir; | |
213 | print cwd() =~ /\Q$dir/i ? "ok 1 parent" : "not ok 1 parent"; | |
214 | chdir ".."; | |
215 | rmdir $dir; | |
216 | } | |
217 | else { | |
218 | sleep 2; | |
219 | $dir = "f$$.tst"; | |
220 | mkdir $dir, 0755; | |
221 | chdir $dir; | |
222 | print cwd() =~ /\Q$dir/i ? "ok 1 child" : "not ok 1 child"; | |
223 | chdir ".."; | |
224 | rmdir $dir; | |
225 | } | |
226 | EXPECT | |
5f7e0818 | 227 | OPTION random |
7766f137 GS |
228 | ok 1 parent |
229 | ok 1 child | |
230 | ######## | |
231 | $| = 1; | |
232 | $\ = "\n"; | |
233 | my $getenv; | |
2986a63f | 234 | if ($^O eq 'MSWin32' || $^O eq 'NetWare') { |
7766f137 GS |
235 | $getenv = qq[$^X -e "print \$ENV{TST}"]; |
236 | } | |
237 | else { | |
238 | $getenv = qq[$^X -e 'print \$ENV{TST}']; | |
239 | } | |
35424068 | 240 | $ENV{TST} = 'foo'; |
7766f137 GS |
241 | if (fork) { |
242 | sleep 1; | |
35424068 GS |
243 | print "parent before: " . `$getenv`; |
244 | $ENV{TST} = 'bar'; | |
245 | print "parent after: " . `$getenv`; | |
7766f137 GS |
246 | } |
247 | else { | |
35424068 GS |
248 | print "child before: " . `$getenv`; |
249 | $ENV{TST} = 'baz'; | |
250 | print "child after: " . `$getenv`; | |
7766f137 GS |
251 | } |
252 | EXPECT | |
5f7e0818 | 253 | OPTION random |
35424068 GS |
254 | child before: foo |
255 | child after: baz | |
256 | parent before: foo | |
257 | parent after: bar | |
7766f137 GS |
258 | ######## |
259 | $| = 1; | |
260 | $\ = "\n"; | |
261 | if ($pid = fork) { | |
262 | waitpid($pid,0); | |
263 | print "parent got $?" | |
264 | } | |
265 | else { | |
266 | exit(42); | |
267 | } | |
268 | EXPECT | |
5f7e0818 | 269 | OPTION random |
7766f137 GS |
270 | parent got 10752 |
271 | ######## | |
272 | $| = 1; | |
273 | $\ = "\n"; | |
274 | my $echo = 'echo'; | |
275 | if ($pid = fork) { | |
276 | waitpid($pid,0); | |
277 | print "parent got $?" | |
278 | } | |
279 | else { | |
280 | exec("$echo foo"); | |
281 | } | |
282 | EXPECT | |
5f7e0818 | 283 | OPTION random |
7766f137 GS |
284 | foo |
285 | parent got 0 | |
286 | ######## | |
287 | if (fork) { | |
288 | die "parent died"; | |
289 | } | |
290 | else { | |
291 | die "child died"; | |
292 | } | |
293 | EXPECT | |
5f7e0818 | 294 | OPTION random |
7766f137 GS |
295 | parent died at - line 2. |
296 | child died at - line 5. | |
297 | ######## | |
298 | if ($pid = fork) { | |
299 | eval { die "parent died" }; | |
300 | print $@; | |
301 | } | |
302 | else { | |
303 | eval { die "child died" }; | |
304 | print $@; | |
305 | } | |
306 | EXPECT | |
5f7e0818 | 307 | OPTION random |
7766f137 GS |
308 | parent died at - line 2. |
309 | child died at - line 6. | |
310 | ######## | |
311 | if (eval q{$pid = fork}) { | |
312 | eval q{ die "parent died" }; | |
313 | print $@; | |
314 | } | |
315 | else { | |
316 | eval q{ die "child died" }; | |
317 | print $@; | |
318 | } | |
319 | EXPECT | |
5f7e0818 | 320 | OPTION random |
7766f137 GS |
321 | parent died at (eval 2) line 1. |
322 | child died at (eval 2) line 1. | |
323 | ######## | |
324 | BEGIN { | |
325 | $| = 1; | |
326 | fork and exit; | |
327 | print "inner\n"; | |
328 | } | |
329 | # XXX In emulated fork(), the child will not execute anything after | |
330 | # the BEGIN block, due to difficulties in recreating the parse stacks | |
331 | # and restarting yyparse() midstream in the child. This can potentially | |
332 | # be overcome by treating what's after the BEGIN{} as a brand new parse. | |
333 | #print "outer\n" | |
334 | EXPECT | |
5f7e0818 | 335 | OPTION random |
7766f137 | 336 | inner |
030866aa GS |
337 | ######## |
338 | sub pipe_to_fork ($$) { | |
339 | my $parent = shift; | |
340 | my $child = shift; | |
341 | pipe($child, $parent) or die; | |
342 | my $pid = fork(); | |
343 | die "fork() failed: $!" unless defined $pid; | |
344 | close($pid ? $child : $parent); | |
345 | $pid; | |
346 | } | |
347 | ||
348 | if (pipe_to_fork('PARENT','CHILD')) { | |
349 | # parent | |
350 | print PARENT "pipe_to_fork\n"; | |
351 | close PARENT; | |
352 | } | |
353 | else { | |
354 | # child | |
355 | while (<CHILD>) { print; } | |
356 | close CHILD; | |
357 | exit; | |
358 | } | |
359 | ||
360 | sub pipe_from_fork ($$) { | |
361 | my $parent = shift; | |
362 | my $child = shift; | |
363 | pipe($parent, $child) or die; | |
364 | my $pid = fork(); | |
365 | die "fork() failed: $!" unless defined $pid; | |
366 | close($pid ? $child : $parent); | |
367 | $pid; | |
368 | } | |
369 | ||
370 | if (pipe_from_fork('PARENT','CHILD')) { | |
371 | # parent | |
372 | while (<PARENT>) { print; } | |
373 | close PARENT; | |
374 | } | |
375 | else { | |
376 | # child | |
377 | print CHILD "pipe_from_fork\n"; | |
378 | close CHILD; | |
379 | exit; | |
380 | } | |
381 | EXPECT | |
5f7e0818 | 382 | OPTION random |
030866aa GS |
383 | pipe_from_fork |
384 | pipe_to_fork | |
68a29c53 | 385 | ######## |
10d51319 | 386 | $|=1; |
68a29c53 GS |
387 | if ($pid = fork()) { |
388 | print "forked first kid\n"; | |
389 | print "waitpid() returned ok\n" if waitpid($pid,0) == $pid; | |
390 | } | |
391 | else { | |
392 | print "first child\n"; | |
393 | exit(0); | |
394 | } | |
395 | if ($pid = fork()) { | |
396 | print "forked second kid\n"; | |
397 | print "wait() returned ok\n" if wait() == $pid; | |
398 | } | |
399 | else { | |
400 | print "second child\n"; | |
401 | exit(0); | |
402 | } | |
403 | EXPECT | |
5f7e0818 | 404 | OPTION random |
68a29c53 GS |
405 | forked first kid |
406 | first child | |
407 | waitpid() returned ok | |
408 | forked second kid | |
409 | second child | |
410 | wait() returned ok | |
a0bd7037 SR |
411 | ######## |
412 | pipe(RDR,WTR) or die $!; | |
413 | my $pid = fork; | |
414 | die "fork: $!" if !defined $pid; | |
415 | if ($pid == 0) { | |
a0bd7037 | 416 | close RDR; |
5bf4f5b3 | 417 | print WTR "STRING_FROM_CHILD\n"; |
a0bd7037 SR |
418 | close WTR; |
419 | } else { | |
a0bd7037 | 420 | close WTR; |
5bf4f5b3 | 421 | chomp(my $string_from_child = <RDR>); |
a0bd7037 | 422 | close RDR; |
5bf4f5b3 | 423 | print $string_from_child eq "STRING_FROM_CHILD", "\n"; |
a0bd7037 SR |
424 | } |
425 | EXPECT | |
5f7e0818 | 426 | OPTION random |
a0bd7037 | 427 | 1 |
d8d97e70 DM |
428 | ######## |
429 | # [perl #39145] Perl_dounwind() crashing with Win32's fork() emulation | |
430 | sub { @_ = 3; fork ? die "1\n" : die "1\n" }->(2); | |
431 | EXPECT | |
5f7e0818 | 432 | OPTION random |
d8d97e70 DM |
433 | 1 |
434 | 1 | |
a1f97a07 DM |
435 | ######## |
436 | # [perl #72604] @DB::args stops working across Win32 fork | |
437 | $|=1; | |
438 | sub f { | |
439 | if ($pid = fork()) { | |
440 | print "waitpid() returned ok\n" if waitpid($pid,0) == $pid; | |
441 | } | |
442 | else { | |
443 | package DB; | |
444 | my @c = caller(0); | |
445 | print "child: called as [$c[3](", join(',',@DB::args), ")]\n"; | |
446 | exit(0); | |
447 | } | |
448 | } | |
449 | f("foo", "bar"); | |
450 | EXPECT | |
5f7e0818 | 451 | OPTION random |
a1f97a07 DM |
452 | child: called as [main::f(foo,bar)] |
453 | waitpid() returned ok | |
82e24582 JD |
454 | ######## |
455 | # Windows 2000: https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976 | |
456 | system $^X, "-e", "if (\$pid=fork){sleep 1;kill(9, \$pid)} else {sleep 5}"; | |
457 | print $?>>8, "\n"; | |
458 | EXPECT | |
459 | 0 | |
460 | ######## | |
461 | # Windows 7: https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976 | |
462 | system $^X, "-e", "if (\$pid=fork){kill(9, \$pid)} else {sleep 5}"; | |
463 | print $?>>8, "\n"; | |
464 | EXPECT | |
465 | 0 | |
8a3cb9c6 JD |
466 | ######## |
467 | # Windows fork() emulation: can we still waitpid() after signalling SIGTERM? | |
468 | $|=1; | |
469 | if (my $pid = fork) { | |
470 | sleep 1; | |
471 | print "1\n"; | |
472 | kill 'TERM', $pid; | |
473 | waitpid($pid, 0); | |
474 | print "4\n"; | |
475 | } | |
476 | else { | |
477 | $SIG{TERM} = sub { print "2\n" }; | |
478 | sleep 3; | |
479 | print "3\n"; | |
480 | } | |
481 | EXPECT | |
482 | 1 | |
483 | 2 | |
484 | 3 | |
485 | 4 |