brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.8 KiB · 931ab86 Raw
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