This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #93320] localising @DB::args leads to coredump
[perl5.git] / t / op / fork.t
CommitLineData
8d063cd8
LW
1#!./perl
2
7766f137 3# tests for both real and emulated fork()
8d063cd8 4
774d564b 5BEGIN {
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
14skip_all('fork/status problems on MPE/iX')
15 if $^O eq 'mpeix';
0994c4d0 16
7766f137
GS
17$|=1;
18
5f7e0818 19run_multiple_progs('', \*DATA);
7766f137 20
5f7e0818 21done_testing();
7766f137
GS
22
23__END__
24$| = 1;
8d063cd8 25if ($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}
35else {
8d063cd8
LW
36 print "ok 1\n";
37 sleep 10;
38}
7766f137 39EXPECT
5f7e0818 40OPTION random
7766f137
GS
41ok 1
42ok 2
43########
44$| = 1;
aeecf691
JD
45if ($cid = fork) {
46 sleep 1;
47 print "not " unless kill 'INT', $cid;
48 print "ok 2\n";
49}
50else {
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}
58EXPECT
5f7e0818 59OPTION random
aeecf691
JD
60ok 1
61ok 2
62########
63$| = 1;
7766f137
GS
64sub 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}
79while ($i++ < 3) { do { forkit(); }; }
80EXPECT
5f7e0818 81OPTION random
7766f137
GS
82iteration 1 start
83iteration 1 parent
84iteration 1 child
85iteration 2 start
86iteration 2 parent
87iteration 2 child
88iteration 2 start
89iteration 2 parent
90iteration 2 child
91iteration 3 start
92iteration 3 parent
93iteration 3 child
94iteration 3 start
95iteration 3 parent
96iteration 3 child
97iteration 3 start
98iteration 3 parent
99iteration 3 child
100iteration 3 start
101iteration 3 parent
102iteration 3 child
103########
104$| = 1;
105fork()
106 ? (print("parent\n"),sleep(1))
107 : (print("child\n"),exit) ;
108EXPECT
5f7e0818 109OPTION random
7766f137
GS
110parent
111child
112########
113$| = 1;
114fork()
115 ? (print("parent\n"),exit)
116 : (print("child\n"),sleep(1)) ;
117EXPECT
5f7e0818 118OPTION random
7766f137
GS
119parent
120child
121########
122$| = 1;
123@a = (1..3);
124for (@a) {
125 if (fork) {
126 print "parent $_\n";
127 $_ = "[$_]";
128 }
129 else {
130 print "child $_\n";
131 $_ = "-$_-";
132 }
133}
134print "@a\n";
135EXPECT
5f7e0818 136OPTION random
7766f137
GS
137parent 1
138child 1
139parent 2
140child 2
141parent 2
142child 2
143parent 3
144child 3
145parent 3
146child 3
147parent 3
148child 3
149parent 3
150child 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;
161foreach 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}
170while (wait() != -1) { print "waited\n" }
171EXPECT
5f7e0818 172OPTION random
c3564e5c
GS
173child 1
174child 2
175child 3
176parent 1
177parent 2
178parent 3
179waited
180waited
181waited
182########
7766f137
GS
183use Config;
184$| = 1;
185$\ = "\n";
186fork()
187 ? print($Config{osname} eq $^O)
188 : print($Config{osname} eq $^O) ;
189EXPECT
5f7e0818 190OPTION random
7766f137
GS
1911
1921
193########
194$| = 1;
195$\ = "\n";
196fork()
197 ? do { require Config; print($Config::Config{osname} eq $^O); }
198 : do { require Config; print($Config::Config{osname} eq $^O); }
199EXPECT
5f7e0818 200OPTION random
7766f137
GS
2011
2021
203########
204$| = 1;
205use Cwd;
cf2f24a4 206my $cwd = cwd(); # Make sure we load Win32.pm while "../lib" still works.
7766f137
GS
207$\ = "\n";
208my $dir;
209if (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}
217else {
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}
226EXPECT
5f7e0818 227OPTION random
7766f137
GS
228ok 1 parent
229ok 1 child
230########
231$| = 1;
232$\ = "\n";
233my $getenv;
2986a63f 234if ($^O eq 'MSWin32' || $^O eq 'NetWare') {
7766f137
GS
235 $getenv = qq[$^X -e "print \$ENV{TST}"];
236}
237else {
238 $getenv = qq[$^X -e 'print \$ENV{TST}'];
239}
35424068 240$ENV{TST} = 'foo';
7766f137
GS
241if (fork) {
242 sleep 1;
35424068
GS
243 print "parent before: " . `$getenv`;
244 $ENV{TST} = 'bar';
245 print "parent after: " . `$getenv`;
7766f137
GS
246}
247else {
35424068
GS
248 print "child before: " . `$getenv`;
249 $ENV{TST} = 'baz';
250 print "child after: " . `$getenv`;
7766f137
GS
251}
252EXPECT
5f7e0818 253OPTION random
35424068
GS
254child before: foo
255child after: baz
256parent before: foo
257parent after: bar
7766f137
GS
258########
259$| = 1;
260$\ = "\n";
261if ($pid = fork) {
262 waitpid($pid,0);
263 print "parent got $?"
264}
265else {
266 exit(42);
267}
268EXPECT
5f7e0818 269OPTION random
7766f137
GS
270parent got 10752
271########
272$| = 1;
273$\ = "\n";
274my $echo = 'echo';
275if ($pid = fork) {
276 waitpid($pid,0);
277 print "parent got $?"
278}
279else {
280 exec("$echo foo");
281}
282EXPECT
5f7e0818 283OPTION random
7766f137
GS
284foo
285parent got 0
286########
287if (fork) {
288 die "parent died";
289}
290else {
291 die "child died";
292}
293EXPECT
5f7e0818 294OPTION random
7766f137
GS
295parent died at - line 2.
296child died at - line 5.
297########
298if ($pid = fork) {
299 eval { die "parent died" };
300 print $@;
301}
302else {
303 eval { die "child died" };
304 print $@;
305}
306EXPECT
5f7e0818 307OPTION random
7766f137
GS
308parent died at - line 2.
309child died at - line 6.
310########
311if (eval q{$pid = fork}) {
312 eval q{ die "parent died" };
313 print $@;
314}
315else {
316 eval q{ die "child died" };
317 print $@;
318}
319EXPECT
5f7e0818 320OPTION random
7766f137
GS
321parent died at (eval 2) line 1.
322child died at (eval 2) line 1.
323########
324BEGIN {
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"
334EXPECT
5f7e0818 335OPTION random
7766f137 336inner
030866aa
GS
337########
338sub 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
348if (pipe_to_fork('PARENT','CHILD')) {
349 # parent
350 print PARENT "pipe_to_fork\n";
351 close PARENT;
352}
353else {
354 # child
355 while (<CHILD>) { print; }
356 close CHILD;
357 exit;
358}
359
360sub 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
370if (pipe_from_fork('PARENT','CHILD')) {
371 # parent
372 while (<PARENT>) { print; }
373 close PARENT;
374}
375else {
376 # child
377 print CHILD "pipe_from_fork\n";
378 close CHILD;
379 exit;
380}
381EXPECT
5f7e0818 382OPTION random
030866aa
GS
383pipe_from_fork
384pipe_to_fork
68a29c53 385########
10d51319 386$|=1;
68a29c53
GS
387if ($pid = fork()) {
388 print "forked first kid\n";
389 print "waitpid() returned ok\n" if waitpid($pid,0) == $pid;
390}
391else {
392 print "first child\n";
393 exit(0);
394}
395if ($pid = fork()) {
396 print "forked second kid\n";
397 print "wait() returned ok\n" if wait() == $pid;
398}
399else {
400 print "second child\n";
401 exit(0);
402}
403EXPECT
5f7e0818 404OPTION random
68a29c53
GS
405forked first kid
406first child
407waitpid() returned ok
408forked second kid
409second child
410wait() returned ok
a0bd7037
SR
411########
412pipe(RDR,WTR) or die $!;
413my $pid = fork;
414die "fork: $!" if !defined $pid;
415if ($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}
425EXPECT
5f7e0818 426OPTION random
a0bd7037 4271
d8d97e70
DM
428########
429# [perl #39145] Perl_dounwind() crashing with Win32's fork() emulation
430sub { @_ = 3; fork ? die "1\n" : die "1\n" }->(2);
431EXPECT
5f7e0818 432OPTION random
d8d97e70
DM
4331
4341
a1f97a07
DM
435########
436# [perl #72604] @DB::args stops working across Win32 fork
437$|=1;
438sub 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}
449f("foo", "bar");
450EXPECT
5f7e0818 451OPTION random
a1f97a07
DM
452child: called as [main::f(foo,bar)]
453waitpid() returned ok
82e24582
JD
454########
455# Windows 2000: https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
456system $^X, "-e", "if (\$pid=fork){sleep 1;kill(9, \$pid)} else {sleep 5}";
457print $?>>8, "\n";
458EXPECT
4590
460########
461# Windows 7: https://rt.cpan.org/Ticket/Display.html?id=66016#txn-908976
462system $^X, "-e", "if (\$pid=fork){kill(9, \$pid)} else {sleep 5}";
463print $?>>8, "\n";
464EXPECT
4650
8a3cb9c6
JD
466########
467# Windows fork() emulation: can we still waitpid() after signalling SIGTERM?
468$|=1;
469if (my $pid = fork) {
470 sleep 1;
471 print "1\n";
472 kill 'TERM', $pid;
473 waitpid($pid, 0);
474 print "4\n";
475}
476else {
477 $SIG{TERM} = sub { print "2\n" };
478 sleep 3;
479 print "3\n";
480}
481EXPECT
4821
4832
4843
4854