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