]>
Commit | Line | Data |
---|---|---|
2546420a A |
1 | #include <pthread.h> |
2 | ||
a0619f9c | 3 | #include "darwintest_defaults.h" |
2546420a A |
4 | |
5 | static volatile int once_invoked = 0; | |
6 | ||
7 | static void | |
8 | cancelation_handler(void * __unused arg) | |
9 | { | |
10 | T_LOG("cancelled"); | |
11 | } | |
12 | ||
13 | __attribute__((noreturn)) | |
14 | static void | |
15 | await_cancelation(void) | |
16 | { | |
17 | pthread_cleanup_push(cancelation_handler, NULL); | |
18 | T_LOG("waiting for cancellation"); | |
19 | ||
20 | // can't use darwintest once cancellation is enabled | |
21 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); | |
22 | ||
23 | while (true) { | |
24 | pthread_testcancel(); | |
25 | sched_yield(); | |
26 | } | |
27 | ||
28 | pthread_cleanup_pop(0); | |
29 | } | |
30 | ||
31 | static void * | |
32 | await_cancelation_in_once(void *arg) | |
33 | { | |
34 | // disable cancellation until pthread_once to protect darwintest | |
35 | pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); | |
36 | ||
37 | T_LOG("starting the thread"); | |
38 | pthread_once_t *once = (pthread_once_t *)arg; | |
39 | pthread_once(once, await_cancelation); | |
40 | return NULL; | |
41 | } | |
42 | ||
43 | static void | |
44 | oncef(void) | |
45 | { | |
46 | T_LOG("once invoked"); | |
47 | once_invoked++; | |
48 | } | |
49 | ||
50 | T_DECL(once_cancel, "pthread_once is re-executed if cancelled") | |
51 | { | |
52 | pthread_once_t once = PTHREAD_ONCE_INIT; | |
53 | pthread_t t; | |
54 | void *join_result = NULL; | |
55 | ||
56 | T_ASSERT_POSIX_ZERO( | |
57 | pthread_create(&t, NULL, await_cancelation_in_once, &once), NULL); | |
58 | T_ASSERT_POSIX_ZERO(pthread_cancel(t), NULL); | |
59 | T_ASSERT_POSIX_ZERO(pthread_join(t, &join_result), NULL); | |
60 | T_ASSERT_EQ(join_result, PTHREAD_CANCELED, NULL); | |
61 | ||
62 | T_ASSERT_POSIX_ZERO(pthread_once(&once, oncef), NULL); | |
63 | T_ASSERT_EQ(once_invoked, 1, NULL); | |
64 | } |