| 1 | // Check that init-order checking is properly disabled if pthread_create is |
| 2 | // called. |
| 3 | |
| 4 | // RUN: %clangxx_asan -c -DCONFIG1 %s -o %t1.o |
| 5 | // RUN: %clangxx_asan -c %s -o %t2.o |
| 6 | // RUN: %clangxx_asan -pthread %t1.o %t2.o -o %t |
| 7 | // RUN: %env_asan_opts=strict_init_order=true %run %t |
| 8 | |
| 9 | #ifdef CONFIG1 |
| 10 | |
| 11 | #include <stdio.h> |
| 12 | #include <pthread.h> |
| 13 | #include <unistd.h> |
| 14 | |
| 15 | void *bar(void *input, bool sleep_before_init) { |
| 16 | if (sleep_before_init) |
| 17 | usleep(500000); |
| 18 | return input; |
| 19 | } |
| 20 | |
| 21 | void *glob = bar((void*)0x1234, false); |
| 22 | extern void *glob2; |
| 23 | |
| 24 | void *poll(void *arg) { |
| 25 | void **glob = (void**)arg; |
| 26 | while (true) { |
| 27 | usleep(100000); |
| 28 | printf("glob is now: %p\n" , *glob); |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | struct GlobalPollerStarter { |
| 33 | GlobalPollerStarter() { |
| 34 | pthread_t p; |
| 35 | pthread_attr_t attr; |
| 36 | pthread_attr_init(&attr); |
| 37 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| 38 | pthread_create(&p, 0, poll, &glob); |
| 39 | pthread_attr_destroy(&attr); |
| 40 | printf("glob poller is started" ); |
| 41 | } |
| 42 | } global_poller; |
| 43 | |
| 44 | int main() { |
| 45 | printf("%p %p\n" , glob, glob2); |
| 46 | return 0; |
| 47 | } |
| 48 | |
| 49 | #else // CONFIG1 |
| 50 | |
| 51 | void *bar(void *input, bool sleep_before_init); |
| 52 | void *glob2 = bar(input: (void*)0x2345, sleep_before_init: true); |
| 53 | |
| 54 | #endif |
| 55 | |