1*b39c5158Smillertuse strict; 2*b39c5158Smillertuse warnings; 3*b39c5158Smillert 4*b39c5158SmillertBEGIN { 5*b39c5158Smillert use Config; 6*b39c5158Smillert if (! $Config{'useithreads'}) { 7*b39c5158Smillert print("1..0 # SKIP Perl not compiled with 'useithreads'\n"); 8*b39c5158Smillert exit(0); 9*b39c5158Smillert } 10*b39c5158Smillert} 11*b39c5158Smillert 12*b39c5158Smillertuse ExtUtils::testlib; 13*b39c5158Smillert 14*b39c5158Smillertuse threads; 15*b39c5158Smillert 16*b39c5158SmillertBEGIN { 17*b39c5158Smillert if (! eval 'use threads::shared; 1') { 18*b39c5158Smillert print("1..0 # SKIP threads::shared not available\n"); 19*b39c5158Smillert exit(0); 20*b39c5158Smillert } 21*b39c5158Smillert 22*b39c5158Smillert $| = 1; 23*b39c5158Smillert print("1..20\n"); ### Number of tests that will be run ### 24*b39c5158Smillert}; 25*b39c5158Smillert 26*b39c5158Smillertmy $TEST; 27*b39c5158SmillertBEGIN { 28*b39c5158Smillert share($TEST); 29*b39c5158Smillert $TEST = 1; 30*b39c5158Smillert} 31*b39c5158Smillert 32*b39c5158Smillertok(1, 'Loaded'); 33*b39c5158Smillert 34*b39c5158Smillertsub ok { 35*b39c5158Smillert my ($ok, $name) = @_; 36*b39c5158Smillert 37*b39c5158Smillert lock($TEST); 38*b39c5158Smillert my $id = $TEST++; 39*b39c5158Smillert 40*b39c5158Smillert # You have to do it this way or VMS will get confused. 41*b39c5158Smillert if ($ok) { 42*b39c5158Smillert print("ok $id - $name\n"); 43*b39c5158Smillert } else { 44*b39c5158Smillert print("not ok $id - $name\n"); 45*b39c5158Smillert printf("# Failed test at line %d\n", (caller)[2]); 46*b39c5158Smillert } 47*b39c5158Smillert 48*b39c5158Smillert return ($ok); 49*b39c5158Smillert} 50*b39c5158Smillert 51*b39c5158Smillertsub skip { 52*b39c5158Smillert ok(1, '# SKIP ' . $_[0]); 53*b39c5158Smillert} 54*b39c5158Smillert 55*b39c5158Smillert 56*b39c5158Smillert### Start of Testing ### 57*b39c5158Smillert 58*b39c5158Smillert{ 59*b39c5158Smillert my $retval = threads->create(sub { return ("hi") })->join(); 60*b39c5158Smillert ok($retval eq 'hi', "Check basic returnvalue"); 61*b39c5158Smillert} 62*b39c5158Smillert{ 63*b39c5158Smillert my ($thread) = threads->create(sub { return (1,2,3) }); 64*b39c5158Smillert my @retval = $thread->join(); 65*b39c5158Smillert ok($retval[0] == 1 && $retval[1] == 2 && $retval[2] == 3,''); 66*b39c5158Smillert} 67*b39c5158Smillert{ 68*b39c5158Smillert my $retval = threads->create(sub { return [1] })->join(); 69*b39c5158Smillert ok($retval->[0] == 1,"Check that a array ref works",); 70*b39c5158Smillert} 71*b39c5158Smillert{ 72*b39c5158Smillert my $retval = threads->create(sub { return { foo => "bar" }})->join(); 73*b39c5158Smillert ok($retval->{foo} eq 'bar',"Check that hash refs work"); 74*b39c5158Smillert} 75*b39c5158Smillert{ 76*b39c5158Smillert my $retval = threads->create( sub { 77*b39c5158Smillert open(my $fh, "+>threadtest") || die $!; 78*b39c5158Smillert print $fh "test\n"; 79*b39c5158Smillert return $fh; 80*b39c5158Smillert })->join(); 81*b39c5158Smillert ok(ref($retval) eq 'GLOB', "Check that we can return FH $retval"); 82*b39c5158Smillert print $retval "test2\n"; 83*b39c5158Smillert close($retval); 84*b39c5158Smillert unlink("threadtest"); 85*b39c5158Smillert} 86*b39c5158Smillert{ 87*b39c5158Smillert my $test = "hi"; 88*b39c5158Smillert my $retval = threads->create(sub { return $_[0]}, \$test)->join(); 89*b39c5158Smillert ok($$retval eq 'hi',''); 90*b39c5158Smillert} 91*b39c5158Smillert{ 92*b39c5158Smillert my $test = "hi"; 93*b39c5158Smillert share($test); 94*b39c5158Smillert my $retval = threads->create(sub { return $_[0]}, \$test)->join(); 95*b39c5158Smillert ok($$retval eq 'hi',''); 96*b39c5158Smillert $test = "foo"; 97*b39c5158Smillert ok($$retval eq 'foo',''); 98*b39c5158Smillert} 99*b39c5158Smillert{ 100*b39c5158Smillert my %foo; 101*b39c5158Smillert share(%foo); 102*b39c5158Smillert threads->create(sub { 103*b39c5158Smillert my $foo; 104*b39c5158Smillert share($foo); 105*b39c5158Smillert $foo = "thread1"; 106*b39c5158Smillert return $foo{bar} = \$foo; 107*b39c5158Smillert })->join(); 108*b39c5158Smillert ok(1,""); 109*b39c5158Smillert} 110*b39c5158Smillert 111*b39c5158Smillert# We parse ps output so this is OS-dependent. 112*b39c5158Smillertif ($^O eq 'linux') { 113*b39c5158Smillert # First modify $0 in a subthread. 114*b39c5158Smillert #print "# mainthread: \$0 = $0\n"; 115*b39c5158Smillert threads->create(sub{ #print "# subthread: \$0 = $0\n"; 116*b39c5158Smillert $0 = "foobar"; 117*b39c5158Smillert #print "# subthread: \$0 = $0\n" 118*b39c5158Smillert })->join; 119*b39c5158Smillert #print "# mainthread: \$0 = $0\n"; 120*b39c5158Smillert #print "# pid = $$\n"; 121*b39c5158Smillert if (open PS, "ps -f |") { # Note: must work in (all) systems. 122*b39c5158Smillert my ($sawpid, $sawexe); 123*b39c5158Smillert while (<PS>) { 124*b39c5158Smillert chomp; 125*b39c5158Smillert #print "# [$_]\n"; 126*b39c5158Smillert if (/^\s*\S+\s+$$\s/) { 127*b39c5158Smillert $sawpid++; 128*b39c5158Smillert if (/\sfoobar\s*$/) { # Linux 2.2 leaves extra trailing spaces. 129*b39c5158Smillert $sawexe++; 130*b39c5158Smillert } 131*b39c5158Smillert last; 132*b39c5158Smillert } 133*b39c5158Smillert } 134*b39c5158Smillert close PS or die; 135*b39c5158Smillert if ($sawpid) { 136*b39c5158Smillert ok($sawpid && $sawexe, 'altering $0 is effective'); 137*b39c5158Smillert } else { 138*b39c5158Smillert skip("\$0 check: did not see pid $$ in 'ps -f |'"); 139*b39c5158Smillert } 140*b39c5158Smillert } else { 141*b39c5158Smillert skip("\$0 check: opening 'ps -f |' failed: $!"); 142*b39c5158Smillert } 143*b39c5158Smillert} else { 144*b39c5158Smillert skip("\$0 check: only on Linux"); 145*b39c5158Smillert} 146*b39c5158Smillert 147*b39c5158Smillert{ 148*b39c5158Smillert my $t = threads->create(sub {}); 149*b39c5158Smillert $t->join(); 150*b39c5158Smillert threads->create(sub {})->join(); 151*b39c5158Smillert eval { $t->join(); }; 152*b39c5158Smillert ok(($@ =~ /Thread already joined/), "Double join works"); 153*b39c5158Smillert eval { $t->detach(); }; 154*b39c5158Smillert ok(($@ =~ /Cannot detach a joined thread/), "Detach joined thread"); 155*b39c5158Smillert} 156*b39c5158Smillert 157*b39c5158Smillert{ 158*b39c5158Smillert my $t = threads->create(sub {}); 159*b39c5158Smillert $t->detach(); 160*b39c5158Smillert threads->create(sub {})->join(); 161*b39c5158Smillert eval { $t->detach(); }; 162*b39c5158Smillert ok(($@ =~ /Thread already detached/), "Double detach works"); 163*b39c5158Smillert eval { $t->join(); }; 164*b39c5158Smillert ok(($@ =~ /Cannot join a detached thread/), "Join detached thread"); 165*b39c5158Smillert} 166*b39c5158Smillert 167*b39c5158Smillert{ 168*b39c5158Smillert # The "use IO::File" is not actually used for anything; its only purpose 169*b39c5158Smillert # is incite a lot of calls to newCONSTSUB. See the p5p archives for 170*b39c5158Smillert # the thread "maint@20974 or before broke mp2 ithreads test". 171*b39c5158Smillert use IO::File; 172*b39c5158Smillert # This coredumped between #20930 and #21000 173*b39c5158Smillert $_->join for map threads->create(sub{ok($_, "stress newCONSTSUB")}), 1..2; 174*b39c5158Smillert} 175*b39c5158Smillert 176*b39c5158Smillert{ 177*b39c5158Smillert my $go : shared = 0; 178*b39c5158Smillert 179*b39c5158Smillert my $t = threads->create( sub { 180*b39c5158Smillert lock($go); 181*b39c5158Smillert cond_wait($go) until $go; 182*b39c5158Smillert }); 183*b39c5158Smillert 184*b39c5158Smillert my $joiner = threads->create(sub { $_[0]->join }, $t); 185*b39c5158Smillert 186*b39c5158Smillert threads->yield(); 187*b39c5158Smillert sleep 1; 188*b39c5158Smillert eval { $t->join; }; 189*b39c5158Smillert ok(($@ =~ /^Thread already joined at/)?1:0, "Join pending join"); 190*b39c5158Smillert 191*b39c5158Smillert { lock($go); $go = 1; cond_signal($go); } 192*b39c5158Smillert $joiner->join; 193*b39c5158Smillert} 194*b39c5158Smillert 195*b39c5158Smillert{ 196*b39c5158Smillert my $go : shared = 0; 197*b39c5158Smillert my $t = threads->create( sub { 198*b39c5158Smillert eval { threads->self->join; }; 199*b39c5158Smillert ok(($@ =~ /^Cannot join self/), "Join self"); 200*b39c5158Smillert lock($go); $go = 1; cond_signal($go); 201*b39c5158Smillert }); 202*b39c5158Smillert 203*b39c5158Smillert { lock ($go); cond_wait($go) until $go; } 204*b39c5158Smillert $t->join; 205*b39c5158Smillert} 206*b39c5158Smillert 207*b39c5158Smillert{ 208*b39c5158Smillert my $go : shared = 0; 209*b39c5158Smillert my $t = threads->create( sub { 210*b39c5158Smillert lock($go); cond_wait($go) until $go; 211*b39c5158Smillert }); 212*b39c5158Smillert my $joiner = threads->create(sub { $_[0]->join; }, $t); 213*b39c5158Smillert 214*b39c5158Smillert threads->yield(); 215*b39c5158Smillert sleep 1; 216*b39c5158Smillert eval { $t->detach }; 217*b39c5158Smillert ok(($@ =~ /^Cannot detach a joined thread at/)?1:0, "Detach pending join"); 218*b39c5158Smillert 219*b39c5158Smillert { lock($go); $go = 1; cond_signal($go); } 220*b39c5158Smillert $joiner->join; 221*b39c5158Smillert} 222*b39c5158Smillert 223*b39c5158Smillertexit(0); 224*b39c5158Smillert 225*b39c5158Smillert# EOF 226