1 // RUN: %clangxx -O1 %s -o %t && env TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s
3 // JVM uses SEGV to preempt threads. All threads do a load from a known address
4 // periodically. When runtime needs to preempt threads, it unmaps the page.
5 // Threads start triggering SEGV one by one. The signal handler blocks
6 // threads while runtime does its thing. Then runtime maps the page again
7 // and resumes the threads.
8 // Previously this pattern conflicted with stop-the-world machinery,
9 // because it briefly reset SEGV handler to SIG_DFL.
10 // As the consequence JVM just silently died.
12 // This test sets memory flushing rate to maximum, then does series of
13 // "benign" SEGVs that are handled by signal handler, and ensures that
14 // the process survive.
24 unsigned long page_size
;
27 void handler(int signo
, siginfo_t
*info
, void *uctx
) {
28 mprotect(guard
, page_size
, PROT_READ
| PROT_WRITE
);
32 page_size
= sysconf(_SC_PAGESIZE
);
33 struct sigaction a
, old
;
34 memset(&a
, 0, sizeof(a
));
35 memset(&old
, 0, sizeof(old
));
36 a
.sa_sigaction
= handler
;
37 a
.sa_flags
= SA_SIGINFO
;
38 sigaction(SIGSEGV
, &a
, &old
);
40 memset(&a
, 0, sizeof(a
));
41 sigaction(SIGSEGV
, 0, &a
);
42 assert(a
.sa_sigaction
== handler
);
43 assert(a
.sa_flags
& SA_SIGINFO
);
45 guard
= mmap(0, 3 * page_size
, PROT_NONE
, MAP_ANON
| MAP_PRIVATE
, -1, 0);
46 guard
= (char*)guard
+ page_size
; // work around a kernel bug
47 for (int i
= 0; i
< 1000000; i
++) {
48 mprotect(guard
, page_size
, PROT_NONE
);
51 sigaction(SIGSEGV
, &old
, 0);
52 fprintf(stderr
, "DONE\n");