summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/signal_catcher.cc6
-rw-r--r--test/ThreadStress/ThreadStress.java10
2 files changed, 15 insertions, 1 deletions
diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc
index 9031c5e..80563e2 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -95,6 +95,12 @@ void SignalCatcher::HandleSigQuit() {
Runtime* runtime = Runtime::Current();
ThreadList* thread_list = runtime->GetThreadList();
+ // We take the heap lock before suspending all threads so we don't end up in a situation where
+ // one of the suspended threads suspended via the implicit FullSuspendCheck on the slow path of
+ // Heap::Lock, which is the only case where a thread can be suspended while holding the heap lock.
+ // (We need the heap lock when we dump the thread list. We could probably fix this by duplicating
+ // more state from java.lang.Thread in struct Thread.)
+ ScopedHeapLock heap_lock;
thread_list->SuspendAll();
std::ostringstream os;
diff --git a/test/ThreadStress/ThreadStress.java b/test/ThreadStress/ThreadStress.java
index c294a38..1f8fb2d 100644
--- a/test/ThreadStress/ThreadStress.java
+++ b/test/ThreadStress/ThreadStress.java
@@ -20,6 +20,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import libcore.io.*;
// Run on host with:
// javac ThreadTest.java && java ThreadStress && rm *.class
@@ -29,7 +30,8 @@ class ThreadStress implements Runnable {
enum Operation {
OOM(1),
- ALLOC(99),
+ SIGQUIT(19),
+ ALLOC(80),
EXIT(50),
WAIT(50);
@@ -194,6 +196,12 @@ class ThreadStress implements Runnable {
case EXIT: {
return;
}
+ case SIGQUIT: {
+ try {
+ Libcore.os.kill(Libcore.os.getpid(), OsConstants.SIGQUIT);
+ } catch (ErrnoException ex) {
+ }
+ }
case WAIT: {
synchronized (lock) {
try {