xref: /openbsd-src/gnu/usr.bin/perl/dist/threads/t/join.t (revision b39c515898423c8d899e35282f4b395f7cad3298)
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