1 // Test that chained origins are fork-safe.
2 // Run a number of threads that create new chained origins, then fork
3 // and verify that origin reads do not deadlock in the child process.
5 // RUN: %clangxx_dfsan %s -o %t
6 // RUN: %run %t 2>&1 | FileCheck %s
8 // RUN: %clangxx_dfsan -mllvm -dfsan-track-origins=1 %s -o %t
9 // RUN: DFSAN_OPTIONS=store_context_size=1000,origin_history_size=0,origin_history_per_stack_limit=0 %run %t 2>&1 | FileCheck %s
18 #include <sys/types.h>
22 #include <sanitizer/dfsan_interface.h>
26 void copy_labels_thread2() {
29 dfsan_set_label(8, (void *)&x
, sizeof(x
));
33 if (__atomic_load_n(&done
, __ATOMIC_RELAXED
))
38 void copy_labels_thread1(int level
) {
40 copy_labels_thread2();
42 copy_labels_thread1(level
- 1);
45 void *copy_labels_thread(void *id
) {
46 copy_labels_thread1((long)id
);
50 // Run through stackdepot in the child process.
51 // If any of the hash table cells are locked, this may deadlock.
55 dfsan_set_label(16, (void *)&x
, sizeof(x
));
56 for (int i
= 0; i
< 10000; ++i
) {
60 write(2, "done\n", 5);
64 const int kThreads
= 10;
65 pthread_t t
[kThreads
];
66 for (int i
= 0; i
< kThreads
; ++i
)
67 pthread_create(&t
[i
], NULL
, copy_labels_thread
, (void *)(long)i
);
72 __atomic_store_n(&done
, 1, __ATOMIC_RELAXED
);
74 while ((p
= wait(NULL
)) == -1) {
83 const int kChildren
= 20;
84 for (int i
= 0; i
< kChildren
; ++i
) {
86 assert(dfsan_get_label(pid
) == 0);
95 for (int i
= 0; i
< kChildren
; ++i
) {
97 while ((p
= wait(NULL
)) == -1) {
104 // Expect 20 (== kChildren) "done" messages.
105 // CHECK-COUNT-20: done