This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add Mark Dootson to AUTHORS
[perl5.git] / t / op / threads.t
CommitLineData
09576c7d
JH
1#!perl
2
f935b2f6
SB
3BEGIN {
4 chdir 't' if -d 't';
996dc718 5 @INC = '../lib';
9708a845 6 require './test.pl';
57690963 7 $| = 1;
f935b2f6 8
9c8416b2 9 skip_all_without_config('useithreads');
62e452a4 10 skip_all_if_miniperl("no dynamic loading on miniperl, no threads");
09576c7d 11
3c78429c 12 plan(25);
f935b2f6 13}
09576c7d
JH
14
15use strict;
16use warnings;
6765206c 17use threads;
f935b2f6
SB
18
19# test that we don't get:
20# Attempt to free unreferenced scalar: SV 0x40173f3c
21fresh_perl_is(<<'EOI', 'ok', { }, 'delete() under threads');
22use threads;
878090d5 23threads->create(sub { my %h=(1,2); delete $h{1}})->join for 1..2;
f935b2f6
SB
24print "ok";
25EOI
26
27#PR24660
28# test that we don't get:
29# Attempt to free unreferenced scalar: SV 0x814e0dc.
30fresh_perl_is(<<'EOI', 'ok', { }, 'weaken ref under threads');
31use threads;
32use Scalar::Util;
33my $data = "a";
34my $obj = \$data;
35my $copy = $obj;
36Scalar::Util::weaken($copy);
878090d5 37threads->create(sub { 1 })->join for (1..1);
f935b2f6
SB
38print "ok";
39EOI
40
41#PR24663
42# test that we don't get:
43# panic: magic_killbackrefs.
44# Scalars leaked: 3
45fresh_perl_is(<<'EOI', 'ok', { }, 'weaken ref #2 under threads');
46package Foo;
47sub new { bless {},shift }
48package main;
49use threads;
50use Scalar::Util qw(weaken);
51my $object = Foo->new;
52my $ref = $object;
53weaken $ref;
878090d5 54threads->create(sub { $ref = $object } )->join; # $ref = $object causes problems
f935b2f6
SB
55print "ok";
56EOI
9850bf21
RH
57
58#PR30333 - sort() crash with threads
59sub mycmp { length($b) <=> length($a) }
60
61sub do_sort_one_thread {
62 my $kid = shift;
63 print "# kid $kid before sort\n";
64 my @list = ( 'x', 'yy', 'zzz', 'a', 'bb', 'ccc', 'aaaaa', 'z',
65 'hello', 's', 'thisisalongname', '1', '2', '3',
66 'abc', 'xyz', '1234567890', 'm', 'n', 'p' );
67
68 for my $j (1..99999) {
69 for my $k (sort mycmp @list) {}
70 }
71 print "# kid $kid after sort, sleeping 1\n";
72 sleep(1);
73 print "# kid $kid exit\n";
74}
75
76sub do_sort_threads {
77 my $nthreads = shift;
78 my @kids = ();
79 for my $i (1..$nthreads) {
878090d5 80 my $t = threads->create(\&do_sort_one_thread, $i);
9850bf21
RH
81 print "# parent $$: continue\n";
82 push(@kids, $t);
83 }
84 for my $t (@kids) {
85 print "# parent $$: waiting for join\n";
86 $t->join();
87 print "# parent $$: thread exited\n";
88 }
89}
90
91do_sort_threads(2); # crashes
92ok(1);
cfae286e
NC
93
94# Change 24643 made the mistake of assuming that CvCONST can only be true on
95# XSUBs. Somehow it can also end up on perl subs.
96fresh_perl_is(<<'EOI', 'ok', { }, 'cloning constant subs');
97use constant x=>1;
98use threads;
99$SIG{__WARN__} = sub{};
100async sub {};
101print "ok";
102EOI
db4997f0
NC
103
104# From a test case by Tim Bunce in
105# http://www.nntp.perl.org/group/perl.perl5.porters/63123
106fresh_perl_is(<<'EOI', 'ok', { }, 'Ensure PL_linestr can be cloned');
107use threads;
e81465be 108print do 'op/threads_create.pl' || die $@;
db4997f0 109EOI
9708a845 110
9708a845
JH
111
112# Scalars leaked: 1
113foreach my $BLOCK (qw(CHECK INIT)) {
114 fresh_perl_is(<<EOI, 'ok', { }, "threads in $BLOCK block");
115 use threads;
116 $BLOCK { threads->create(sub {})->join; }
117 print 'ok';
118EOI
119}
120
121# Scalars leaked: 1
122fresh_perl_is(<<'EOI', 'ok', { }, 'Bug #41138');
123 use threads;
124 leak($x);
125 sub leak
126 {
127 local $x;
128 threads->create(sub {})->join();
129 }
130 print 'ok';
131EOI
132
9708a845 133
f0d3b40c
JH
134# [perl #45053] Memory corruption with heavy module loading in threads
135#
136# run-time usage of newCONSTSUB (as done by the IO boot code) wasn't
137# thread-safe - got occasional coredumps or malloc corruption
138{
76eabe0a 139 local $SIG{__WARN__} = sub {}; # Ignore any thread creation failure warnings
f0d3b40c 140 my @t;
76eabe0a
JH
141 for (1..100) {
142 my $thr = threads->create( sub { require IO });
143 last if !defined($thr); # Probably ran out of memory
144 push(@t, $thr);
145 }
f0d3b40c
JH
146 $_->join for @t;
147 ok(1, '[perl #45053]');
148}
149
f708cfc1
NC
150sub matchit {
151 is (ref $_[1], "Regexp");
152 like ($_[0], $_[1]);
153}
154
155threads->new(\&matchit, "Pie", qr/pie/i)->join();
156
157# tests in threads don't get counted, so
158curr_test(curr_test() + 2);
159
1db36481
DM
160
161# the seen_evals field of a regexp was getting zeroed on clone, so
93f09d7b 162# within a thread it didn't know that a regex object contained a 'safe'
1db36481
DM
163# re_eval expression, so it later died with 'Eval-group not allowed' when
164# you tried to interpolate the object
165
166sub safe_re {
167 my $re = qr/(?{1})/; # this is literal, so safe
168 eval { "a" =~ /$re$re/ }; # interpolating safe values, so safe
169 ok($@ eq "", 'clone seen-evals');
170}
171threads->new(\&safe_re)->join();
172
173# tests in threads don't get counted, so
174curr_test(curr_test() + 1);
175
1dffc4d1
NC
176# This used to crash in 5.10.0 [perl #64954]
177
178undef *a;
179threads->new(sub {})->join;
180pass("undefing a typeglob doesn't cause a crash during cloning");
1db36481 181
7c76c2a0 182
7c76c2a0
JH
183# Test we don't get:
184# panic: del_backref during global destruction.
27bca322
FC
185# when returning a non-closure sub from a thread and subsequently starting
186# a new thread.
187fresh_perl_is(<<'EOI', 'ok', { }, 'No del_backref panic [perl #70748]');
7c76c2a0
JH
188use threads;
189sub foo { return (sub { }); }
190my $bar = threads->create(\&foo)->join();
191threads->create(sub { })->join();
192print "ok";
193EOI
194
27bca322 195# Another, more reliable test for the same del_backref bug:
e4295668
NC
196fresh_perl_is(
197 <<' EOJ', 'ok', {}, 'No del_backref panic [perl #70748] (2)'
27bca322
FC
198 use threads;
199 push @bar, threads->create(sub{sub{}})->join() for 1...10;
200 print "ok";
201 EOJ
202);
203
204# Simple closure-returning test: At least this case works (though it
205# leaks), and we don't want to break it.
e4295668 206fresh_perl_is(<<'EOJ', 'foo', {}, 'returning a closure');
27bca322
FC
207use threads;
208print create threads sub {
e4295668 209 my $x = 'foo';
27bca322
FC
210 sub{sub{$x}}
211}=>->join->()()
212 //"undef"
213EOJ
7c76c2a0 214
3287f6c3
NC
215# At the point of thread creation, $h{1} is on the temps stack.
216# The weak reference $a, however, is visible from the symbol table.
217fresh_perl_is(<<'EOI', 'ok', { }, 'Test for 34394ecd06e704e9');
218 use threads;
219 %h = (1, 2);
220 use Scalar::Util 'weaken';
221 $a = \$h{1};
222 weaken($a);
223 delete $h{1} && threads->create(sub {}, shift)->join();
224 print 'ok';
225EOI
226
f7abe70b
NC
227# This will fail in "interesting" ways if stashes in clone_params is not
228# initialised correctly.
229fresh_perl_like(<<'EOI', qr/\AThread 1 terminated abnormally: Not a CODE reference/, { }, 'RT #73046');
230 use strict;
231 use threads;
232
233 sub foo::bar;
234
235 my %h = (1, *{$::{'foo::'}}{HASH});
236 *{$::{'foo::'}} = {};
237
238 threads->create({}, delete $h{1})->join();
239
240 print "end";
241EOI
242
d08d57ef
NC
243fresh_perl_is(<<'EOI', 'ok', { }, '0 refcnt neither on tmps stack nor in @_');
244 use threads;
245 my %h = (1, []);
246 use Scalar::Util 'weaken';
247 my $a = $h{1};
248 weaken($a);
249 delete $h{1} && threads->create(sub {}, shift)->join();
250 print 'ok';
251EOI
252
05d04d9c
NC
253{
254 my $got;
255 sub stuff {
256 my $a;
257 if (@_) {
258 $a = "Leakage";
259 threads->create(\&stuff)->join();
260 } else {
261 is ($a, undef, 'RT #73086 - clone used to clone active pads');
262 }
263 }
264
265 stuff(1);
266
267 curr_test(curr_test() + 1);
268}
269
adf8f095
NC
270{
271 my $got;
272 sub more_stuff {
273 my $a;
274 $::b = \$a;
275 if (@_) {
276 $a = "More leakage";
277 threads->create(\&more_stuff)->join();
278 } else {
279 is ($a, undef, 'Just special casing lexicals in ?{ ... }');
280 }
281 }
282
283 more_stuff(1);
284
285 curr_test(curr_test() + 1);
286}
287
04518cc3
NC
288# Test from Jerry Hedden, reduced by him from Object::InsideOut's tests.
289fresh_perl_is(<<'EOI', 'ok', { }, '0 refcnt during CLONE');
290use strict;
291use warnings;
292
293use threads;
294
295{
296 package My::Obj;
297 use Scalar::Util 'weaken';
298
299 my %reg;
300
301 sub new
302 {
303 # Create object with ID = 1
304 my $class = shift;
305 my $id = 1;
306 my $obj = bless(\do{ my $scalar = $id; }, $class);
307
308 # Save weak copy of object for reference during cloning
309 weaken($reg{$id} = $obj);
310
311 # Return object
312 return $obj;
313 }
314
315 # Return the internal ID of the object
316 sub id
317 {
318 my $obj = shift;
319 return $$obj;
320 }
321
322 # During cloning 'look' at the object
323 sub CLONE {
324 foreach my $id (keys(%reg)) {
325 # This triggers SvREFCNT_inc() then SvREFCNT_dec() on the referant.
326 my $obj = $reg{$id};
327 }
328 }
329}
330
331# Create object in 'main' thread
332my $obj = My::Obj->new();
333my $id = $obj->id();
334die "\$id is '$id'" unless $id == 1;
335
336# Access object in thread
337threads->create(
338 sub {
339 print $obj->id() == 1 ? "ok\n" : "not ok '" . $obj->id() . "'\n";
340 }
341)->join();
342
343EOI
344
3c78429c
DM
345# make sure peephole optimiser doesn't recurse heavily.
346# (We run this inside a thread to get a small stack)
347
348{
349 # lots of constructs that have o->op_other etc
350 my $code = <<'EOF';
351 $r = $x || $y;
352 $x ||= $y;
353 $r = $x // $y;
354 $x //= $y;
355 $r = $x && $y;
356 $x &&= $y;
357 $r = $x ? $y : $z;
3c78429c
DM
358 @a = map $x+1, @a;
359 @a = grep $x+1, @a;
360 $r = /$x/../$y/;
18e84e81
DM
361
362 # this one will fail since we removed tail recursion optimisation
363 # with f11ca51e41e8
364 #while (1) { $x = 0 };
365
3c78429c
DM
366 while (0) { $x = 0 };
367 for ($x=0; $y; $z=0) { $r = 0 };
368 for (1) { $x = 0 };
369 { $x = 0 };
370 $x =~ s/a/$x + 1/e;
371EOF
2ff884af 372 $code = 'my ($r, $x,$y,$z,@a); return 5; ' . ($code x 1000);
3c78429c
DM
373 my $res = threads->create(sub { eval $code})->join;
374 is($res, 5, "avoid peephole recursion");
375}
376
377
2e0cfa16
FC
378# [perl #78494] Pipes shared between threads block when closed
379watchdog 10;
380{
381 my $perl = which_perl;
382 $perl = qq'"$perl"' if $perl =~ /\s/;
383 open(my $OUT, "|$perl") || die("ERROR: $!");
384 threads->create(sub { })->join;
385 ok(1, "Pipes shared between threads do not block when closed");
386}
387
9708a845 388# EOF