Fail threads attaching during runtime shutdown.
Introduce counters to indicate that threads are being born. Don't allow
thread birth to occur during runtime shutdown.
Bug: 7000936
Change-Id: Ib0d78f78c0ff126a4b5d3b5a6f1a2ff8f5061ae9
diff --git a/src/heap.cc b/src/heap.cc
index 3ab6419..703549f 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -869,6 +869,10 @@
Locks::mutator_lock_->AssertNotHeld(self);
DCHECK_EQ(self->GetState(), kWaitingPerformingGc);
+ if (self->IsHandlingStackOverflow()) {
+ LOG(WARNING) << "Performing GC on a thread that is handling a stack overflow.";
+ }
+
// Ensure there is only one GC at a time.
bool start_collect = false;
while (!start_collect) {
@@ -975,7 +979,7 @@
}
}
- WriterMutexLock mu(*Locks::heap_bitmap_lock_);
+ WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
if (gc_type == kGcTypePartial) {
// Copy the mark bits over from the live bits, do this as early as possible or else we can
// accidentally un-mark roots.
@@ -1921,13 +1925,24 @@
void Heap::RequestConcurrentGC() {
// Make sure that we can do a concurrent GC.
- if (requesting_gc_ || !Runtime::Current()->IsFinishedStarting() ||
- Runtime::Current()->IsShuttingDown() || !Runtime::Current()->IsConcurrentGcEnabled()) {
+ Runtime* runtime = Runtime::Current();
+ if (requesting_gc_ || runtime == NULL || !runtime->IsFinishedStarting() ||
+ !runtime->IsConcurrentGcEnabled()) {
+ return;
+ }
+ Thread* self = Thread::Current();
+ {
+ MutexLock mu(self, *Locks::runtime_shutdown_lock_);
+ if (runtime->IsShuttingDown()) {
+ return;
+ }
+ }
+ if (self->IsHandlingStackOverflow()) {
return;
}
requesting_gc_ = true;
- JNIEnv* env = Thread::Current()->GetJniEnv();
+ JNIEnv* env = self->GetJniEnv();
DCHECK(WellKnownClasses::java_lang_Daemons != NULL);
DCHECK(WellKnownClasses::java_lang_Daemons_requestGC != NULL);
env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,
@@ -1937,8 +1952,11 @@
}
void Heap::ConcurrentGC(Thread* self) {
- if (Runtime::Current()->IsShuttingDown() || !concurrent_gc_) {
- return;
+ {
+ MutexLock mu(self, *Locks::runtime_shutdown_lock_);
+ if (Runtime::Current()->IsShuttingDown() || !concurrent_gc_) {
+ return;
+ }
}
// TODO: We shouldn't need a WaitForConcurrentGcToComplete here since only
@@ -1976,13 +1994,20 @@
return;
}
}
- if (!Runtime::Current()->IsFinishedStarting() || Runtime::Current()->IsShuttingDown()) {
- // Heap trimming isn't supported without a Java runtime or Daemons (such as at dex2oat time)
- // Also: we do not wish to start a heap trim if the runtime is shutting down.
- return;
+
+ Thread* self = Thread::Current();
+ {
+ MutexLock mu(self, *Locks::runtime_shutdown_lock_);
+ Runtime* runtime = Runtime::Current();
+ if (runtime == NULL || !runtime->IsFinishedStarting() || runtime->IsShuttingDown()) {
+ // Heap trimming isn't supported without a Java runtime or Daemons (such as at dex2oat time)
+ // Also: we do not wish to start a heap trim if the runtime is shutting down (a racy check
+ // as we don't hold the lock while requesting the trim).
+ return;
+ }
}
last_trim_time_ = ms_time;
- JNIEnv* env = Thread::Current()->GetJniEnv();
+ JNIEnv* env = self->GetJniEnv();
DCHECK(WellKnownClasses::java_lang_Daemons != NULL);
DCHECK(WellKnownClasses::java_lang_Daemons_requestHeapTrim != NULL);
env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,