17c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0 allow_user_segv_handler=1" %run %t 2>&1 | FileCheck %s
286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// JVM uses SEGV to preempt threads. All threads do a load from a known address
486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// periodically. When runtime needs to preempt threads, it unmaps the page.
586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Threads start triggering SEGV one by one. The signal handler blocks
686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// threads while runtime does its thing. Then runtime maps the page again
786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// and resumes the threads.
886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Previously this pattern conflicted with stop-the-world machinery,
986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// because it briefly reset SEGV handler to SIG_DFL.
1086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// As the consequence JVM just silently died.
1186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
1286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This test sets memory flushing rate to maximum, then does series of
1386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// "benign" SEGVs that are handled by signal handler, and ensures that
1486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// the process survive.
1586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
167c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include <stdio.h>
177c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar#include <stdlib.h>
1886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <signal.h>
1986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include <sys/mman.h>
20799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <string.h>
21799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include <unistd.h>
2286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
23799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarunsigned long page_size;
2486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *guard;
2586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid handler(int signo, siginfo_t *info, void *uctx) {
27799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  mprotect(guard, page_size, PROT_READ | PROT_WRITE);
2886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
2986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
3086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesint main() {
31799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  page_size = sysconf(_SC_PAGESIZE);
327c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  struct sigaction a, old;
33799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  memset(&a, 0, sizeof(a));
34799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  memset(&old, 0, sizeof(old));
3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  a.sa_sigaction = handler;
3686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  a.sa_flags = SA_SIGINFO;
377c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  sigaction(SIGSEGV, &a, &old);
38799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  guard = mmap(0, 3 * page_size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
39799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  guard = (char*)guard + page_size;  // work around a kernel bug
4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  for (int i = 0; i < 1000000; i++) {
41799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    mprotect(guard, page_size, PROT_NONE);
4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    *(int*)guard = 1;
4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
447c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  sigaction(SIGSEGV, &old, 0);
4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  fprintf(stderr, "DONE\n");
4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// CHECK: DONE
49