1 // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s 2 // REQUIRES: linux 3 #include "test.h" 4 5 #include <pthread.h> 6 #include <sys/types.h> 7 #include <unistd.h> 8 9 long count_memory_mappings() { 10 pid_t my_pid = getpid(); 11 char proc_file_name[128]; 12 snprintf(proc_file_name, sizeof(proc_file_name), "/proc/%d/maps", my_pid); 13 14 FILE *proc_file = fopen(proc_file_name, "r"); 15 long line_count = 0; 16 int c; 17 do { 18 c = fgetc(proc_file); 19 if (c == '\n') { 20 line_count++; 21 } 22 } while (c != EOF); 23 fclose(proc_file); 24 25 return line_count; 26 } 27 28 void fiber_iteration() { 29 void *orig_fiber = __tsan_get_current_fiber(); 30 void *fiber = __tsan_create_fiber(0); 31 32 pthread_mutex_t mutex; 33 pthread_mutex_init(&mutex, NULL); 34 35 // Running some code on the fiber that triggers handling of pending signals. 36 __tsan_switch_to_fiber(fiber, 0); 37 pthread_mutex_lock(&mutex); 38 pthread_mutex_unlock(&mutex); 39 __tsan_switch_to_fiber(orig_fiber, 0); 40 41 // We expect the fiber to clean up all resources (here the sigcontext) when destroyed. 42 __tsan_destroy_fiber(fiber); 43 } 44 45 // Magic-Number for some warmup iterations, 46 // as tsan maps some memory for the first runs. 47 const size_t num_warmup = 100; 48 49 int main() { 50 for (size_t i = 0; i < num_warmup; i++) { 51 fiber_iteration(); 52 } 53 54 long memory_mappings_before = count_memory_mappings(); 55 fiber_iteration(); 56 fiber_iteration(); 57 long memory_mappings_after = count_memory_mappings(); 58 59 // Is there a better way to detect a resource leak in the 60 // ThreadState object? (i.e. a mmap not being freed) 61 if (memory_mappings_before == memory_mappings_after) { 62 fprintf(stderr, "PASS\n"); 63 } else { 64 fprintf(stderr, "FAILED\n"); 65 } 66 67 return 0; 68 } 69 70 // CHECK-NOT: WARNING: ThreadSanitizer: 71 // CHECK: PASS 72