]>
Commit | Line | Data |
---|---|---|
3157f602 XL |
1 | // Stress test recovery mode with many threads. |
2 | // | |
3 | // RUN: %clangxx_asan -fsanitize-recover=address -pthread %s -o %t | |
4 | // | |
5 | // RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 1 10 >1.txt 2>&1 | |
6 | // RUN: FileCheck %s < 1.txt | |
7 | // RUN: [ $(grep -c 'ERROR: AddressSanitizer: use-after-poison' 1.txt) -eq 10 ] | |
8 | // RUN: FileCheck --check-prefix=CHECK-NO-COLLISION %s < 1.txt | |
9 | // | |
10 | // Collisions are unlikely but still possible so we need the ||. | |
11 | // RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 10 20 >10.txt 2>&1 || true | |
5bcae85e | 12 | // RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 10.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 10.txt |
3157f602 XL |
13 | // |
14 | // Collisions are unlikely but still possible so we need the ||. | |
15 | // RUN: %env_asan_opts=halt_on_error=false %run %t 10 20 >10.txt 2>&1 || true | |
5bcae85e | 16 | // RUN: FileCheck --check-prefix=CHECK-COLLISION %s < 10.txt || FileCheck --check-prefix=CHECK-NO-COLLISION %s < 10.txt |
3157f602 XL |
17 | |
18 | #include <stdio.h> | |
19 | #include <stdlib.h> | |
20 | #include <pthread.h> | |
21 | #include <time.h> | |
22 | ||
23 | #include <sanitizer/asan_interface.h> | |
24 | ||
25 | size_t nthreads = 10; | |
26 | size_t niter = 10; | |
27 | ||
28 | void random_delay(unsigned *seed) { | |
29 | *seed = 1664525 * *seed + 1013904223; | |
30 | struct timespec delay = { 0, (*seed % 1000) * 1000 }; | |
31 | nanosleep(&delay, 0); | |
32 | } | |
33 | ||
34 | void *run(void *arg) { | |
35 | unsigned seed = (unsigned)(size_t)arg; | |
36 | ||
37 | volatile char tmp[2]; | |
38 | __asan_poison_memory_region(&tmp, sizeof(tmp)); | |
39 | ||
40 | for (size_t i = 0; i < niter; ++i) { | |
41 | random_delay(&seed); | |
42 | // Expect error collisions here | |
43 | // CHECK: ERROR: AddressSanitizer: use-after-poison | |
44 | volatile int idx = 0; | |
45 | tmp[idx] = 0; | |
46 | } | |
47 | ||
48 | return 0; | |
49 | } | |
50 | ||
51 | int main(int argc, char **argv) { | |
52 | if (argc != 3) { | |
53 | fprintf(stderr, "Syntax: %s nthreads niter\n", argv[0]); | |
54 | exit(1); | |
55 | } | |
56 | ||
57 | nthreads = (size_t)strtoul(argv[1], 0, 0); | |
58 | niter = (size_t)strtoul(argv[2], 0, 0); | |
59 | ||
60 | pthread_t *tids = new pthread_t[nthreads]; | |
61 | ||
62 | for (size_t i = 0; i < nthreads; ++i) { | |
63 | if (0 != pthread_create(&tids[i], 0, run, (void *)i)) { | |
64 | fprintf(stderr, "Failed to create thread\n"); | |
65 | exit(1); | |
66 | } | |
67 | } | |
68 | ||
69 | for (size_t i = 0; i < nthreads; ++i) { | |
70 | if (0 != pthread_join(tids[i], 0)) { | |
71 | fprintf(stderr, "Failed to join thread\n"); | |
72 | exit(1); | |
73 | } | |
74 | } | |
75 | ||
76 | // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting | |
77 | // CHECK-NO-COLLISION: All threads terminated | |
78 | printf("All threads terminated\n"); | |
79 | ||
80 | delete [] tids; | |
81 | ||
82 | return 0; | |
83 | } |