1 // RUN: %clangxx -pthread %s -o %t
2 // RUN: %env_tool_opts=detect_invalid_join=false %run %t 0
3
4 // FIXME: Crashes on some bots in pthread_exit.
5 // RUN: %env_tool_opts=detect_invalid_join=false %run %t %if tsan %{ 0 %} %else %{ 1 %}
6
7 // REQUIRES: glibc
8
9 #include <assert.h>
10 #include <ctime>
11 #include <errno.h>
12 #include <pthread.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16
17 bool use_exit;
fn(void * args)18 static void *fn(void *args) {
19 sleep(1);
20 auto ret = (void *)(~(uintptr_t)args);
21 if (use_exit)
22 pthread_exit(ret);
23 return ret;
24 }
25
main(int argc,char ** argv)26 int main(int argc, char **argv) {
27 use_exit = atoi(argv[1]);
28 bool check_invalid_join = !use_exit;
29 pthread_t thread[5];
30 assert(!pthread_create(&thread[0], nullptr, fn, (void *)1000));
31 assert(!pthread_create(&thread[1], nullptr, fn, (void *)1001));
32 assert(!pthread_create(&thread[2], nullptr, fn, (void *)1002));
33 assert(!pthread_create(&thread[3], nullptr, fn, (void *)1003));
34 pthread_attr_t attr;
35 assert(!pthread_attr_init(&attr));
36 assert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
37 assert(!pthread_create(&thread[4], &attr, fn, (void *)1004));
38 assert(!pthread_attr_destroy(&attr));
39
40 assert(!pthread_detach(thread[0]));
41
42 {
43 void *res;
44 while (pthread_tryjoin_np(thread[1], &res))
45 sleep(1);
46 assert(~(uintptr_t)res == 1001);
47 assert(check_invalid_join ||
48 (pthread_tryjoin_np(thread[1], &res) == EBUSY));
49 }
50
51 {
52 void *res;
53 timespec tm = {0, 1};
54 while (pthread_timedjoin_np(thread[2], &res, &tm))
55 sleep(1);
56 assert(~(uintptr_t)res == 1002);
57 assert(check_invalid_join ||
58 (pthread_timedjoin_np(thread[2], &res, &tm) == ESRCH));
59 }
60
61 {
62 void *res;
63 assert(!pthread_join(thread[3], &res));
64 assert(~(uintptr_t)res == 1003);
65 assert(check_invalid_join || (pthread_join(thread[3], &res) == ESRCH));
66 }
67
68 return 0;
69 }
70