1 // Test interaction of Asan recovery mode with asynch signals. 2 // 3 // RUN: %clang_asan -fsanitize-recover=address -pthread %s -o %t 4 // 5 // RUN: rm -f %t.log 6 // RUN: %env_asan_opts=halt_on_error=false:suppress_equal_pcs=false %run %t 100 >%t.log 2>&1 || true 7 // Collision will almost always get triggered but we still need to check the unlikely case: 8 // RUN: FileCheck --check-prefix=CHECK-COLLISION %s < %t.log || FileCheck --check-prefix=CHECK-NO-COLLISION %s < %t.log 9 10 #define _SVID_SOURCE 1 // SA_NODEFER 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <pthread.h> 16 #include <time.h> 17 #include <signal.h> 18 19 #include <sanitizer/asan_interface.h> 20 21 void random_delay(unsigned *seed) { 22 *seed = 1664525 * *seed + 1013904223; 23 struct timespec delay = { 0, (*seed % 1000) * 1000 }; 24 nanosleep(&delay, 0); 25 } 26 27 volatile char bad[2] = {1, }; 28 29 void error() { 30 // CHECK-COLLISION: AddressSanitizer: nested bug in the same thread, aborting 31 // CHECK-NO-COLLISION: AddressSanitizer: use-after-poison 32 volatile int idx = 0; 33 bad[idx] = 0; 34 } 35 36 #define CHECK_CALL(e, msg) do { \ 37 if (0 != (e)) { \ 38 fprintf(stderr, "Failed to " msg "\n"); \ 39 exit(1); \ 40 } \ 41 } while (0) 42 43 size_t niter = 10; 44 pthread_t sender_tid, receiver_tid; 45 46 pthread_mutex_t keep_alive_mu = PTHREAD_MUTEX_INITIALIZER; 47 48 void *sender(void *arg) { 49 unsigned seed = 0; 50 for (size_t i = 0; i < niter; ++i) { 51 random_delay(&seed); 52 CHECK_CALL(pthread_kill(receiver_tid, SIGUSR1), "send signal"); 53 } 54 return 0; 55 } 56 57 void handler(int sig) { 58 // Expect error collisions here 59 error(); 60 } 61 62 void *receiver(void *arg) { 63 unsigned seed = 1; 64 for (size_t i = 0; i < niter; ++i) { 65 random_delay(&seed); 66 // And here 67 error(); 68 } 69 // Parent will release this when it's ok to terminate 70 CHECK_CALL(pthread_mutex_lock(&keep_alive_mu), "unlock mutex"); 71 return 0; 72 } 73 74 int main(int argc, char **argv) { 75 if (argc != 2) { 76 fprintf(stderr, "Syntax: %s niter\n", argv[0]); 77 exit(1); 78 } 79 80 niter = (size_t)strtoul(argv[1], 0, 0); 81 82 struct sigaction sa; 83 memset(&sa, 0, sizeof(sa)); 84 sa.sa_handler = handler; 85 sa.sa_flags = SA_NODEFER; // Enable nested handlers to add more stress 86 CHECK_CALL(sigaction(SIGUSR1, &sa, 0), "set sighandler"); 87 88 __asan_poison_memory_region(&bad, sizeof(bad)); 89 90 CHECK_CALL(pthread_mutex_lock(&keep_alive_mu), "lock mutex"); 91 CHECK_CALL(pthread_create(&receiver_tid, 0, receiver, 0), "start thread"); 92 CHECK_CALL(pthread_create(&sender_tid, 0, sender, 0), "start thread"); 93 CHECK_CALL(pthread_join(sender_tid, 0), "join thread"); 94 // Now allow receiver to die 95 CHECK_CALL(pthread_mutex_unlock(&keep_alive_mu), "unlock mutex"); 96 CHECK_CALL(pthread_join(receiver_tid, 0), "join thread"); 97 98 // CHECK-NO-COLLISION: All threads terminated 99 printf("All threads terminated\n"); 100 101 return 0; 102 } 103