106 lines · cpp
1// Test that chained origins are fork-safe.2// Run a number of threads that create new chained origins, then fork3// and verify that origin reads do not deadlock in the child process.4//5// RUN: %clangxx_dfsan %s -o %t6// RUN: %run %t 2>&1 | FileCheck %s7//8// RUN: %clangxx_dfsan -mllvm -dfsan-track-origins=1 %s -o %t9// RUN: env DFSAN_OPTIONS=store_context_size=1000,origin_history_size=0,origin_history_per_stack_limit=0 %run %t 2>&1 | FileCheck %s10 11#include <assert.h>12#include <errno.h>13#include <pthread.h>14#include <signal.h>15#include <stdio.h>16#include <stdlib.h>17#include <sys/time.h>18#include <sys/types.h>19#include <sys/wait.h>20#include <unistd.h>21 22#include <sanitizer/dfsan_interface.h>23 24int done;25 26void copy_labels_thread2() {27 volatile int x = 0;28 volatile int v = 0;29 dfsan_set_label(8, (void *)&x, sizeof(x));30 while (true) {31 v = x;32 x = v;33 if (__atomic_load_n(&done, __ATOMIC_RELAXED))34 return;35 }36}37 38void copy_labels_thread1(int level) {39 if (!level)40 copy_labels_thread2();41 else42 copy_labels_thread1(level - 1);43}44 45void *copy_labels_thread(void *id) {46 copy_labels_thread1((long)id);47 return 0;48}49 50// Run through stackdepot in the child process.51// If any of the hash table cells are locked, this may deadlock.52void child() {53 volatile int x = 0;54 volatile int v = 0;55 dfsan_set_label(16, (void *)&x, sizeof(x));56 for (int i = 0; i < 10000; ++i) {57 v = x;58 x = v;59 }60 write(2, "done\n", 5);61}62 63void test() {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);68 usleep(100000);69 pid_t pid = fork();70 if (pid) {71 // parent72 __atomic_store_n(&done, 1, __ATOMIC_RELAXED);73 pid_t p;74 while ((p = wait(NULL)) == -1) {75 }76 } else {77 // child78 child();79 }80}81 82int main() {83 const int kChildren = 20;84 for (int i = 0; i < kChildren; ++i) {85 pid_t pid = fork();86 assert(dfsan_get_label(pid) == 0);87 if (pid) {88 // parent89 } else {90 test();91 exit(0);92 }93 }94 95 for (int i = 0; i < kChildren; ++i) {96 pid_t p;97 while ((p = wait(NULL)) == -1) {98 }99 }100 101 return 0;102}103 104// Expect 20 (== kChildren) "done" messages.105// CHECK-COUNT-20: done106