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; |
18 | static void *fn(void *args) { |
19 | sleep(seconds: 1); |
20 | auto ret = (void *)(~(uintptr_t)args); |
21 | if (use_exit) |
22 | pthread_exit(retval: ret); |
23 | return ret; |
24 | } |
25 | |
26 | int main(int argc, char **argv) { |
27 | use_exit = atoi(nptr: 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(th: thread[1], thread_return: &res)) |
45 | sleep(seconds: 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 = {.tv_sec: 0, .tv_nsec: 1}; |
54 | while (pthread_timedjoin_np(th: thread[2], thread_return: &res, abstime: &tm)) |
55 | sleep(seconds: 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 | |