summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/base/mutex.cc23
-rw-r--r--test/132-daemon-locks-shutdown/expected.txt0
-rw-r--r--test/132-daemon-locks-shutdown/info.txt1
-rw-r--r--test/132-daemon-locks-shutdown/src/Main.java53
4 files changed, 67 insertions, 10 deletions
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 17b2ac9..9453741 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -319,19 +319,24 @@ Mutex::Mutex(const char* name, LockLevel level, bool recursive)
exclusive_owner_ = 0;
}
+// Helper to ignore the lock requirement.
+static bool IsShuttingDown() NO_THREAD_SAFETY_ANALYSIS {
+ Runtime* runtime = Runtime::Current();
+ return runtime == nullptr || runtime->IsShuttingDownLocked();
+}
+
Mutex::~Mutex() {
+ bool shutting_down = IsShuttingDown();
#if ART_USE_FUTEXES
if (state_.LoadRelaxed() != 0) {
- Runtime* runtime = Runtime::Current();
- bool shutting_down = runtime == nullptr || runtime->IsShuttingDown(Thread::Current());
LOG(shutting_down ? WARNING : FATAL) << "destroying mutex with owner: " << exclusive_owner_;
} else {
- CHECK_EQ(exclusive_owner_, 0U) << "unexpectedly found an owner on unlocked mutex " << name_;
- if (level_ != kMonitorLock) {
- // Only check the lock level for non monitor locks since we may still have java threads
- // waiting on monitors.
- CHECK_EQ(num_contenders_.LoadSequentiallyConsistent(), 0)
- << "unexpectedly found a contender on mutex " << name_;
+ if (exclusive_owner_ != 0) {
+ LOG(shutting_down ? WARNING : FATAL) << "unexpectedly found an owner on unlocked mutex "
+ << name_;
+ }
+ if (num_contenders_.LoadSequentiallyConsistent() != 0) {
+ LOG(shutting_down ? WARNING : FATAL) << "unexpectedly found a contender on mutex " << name_;
}
}
#else
@@ -342,8 +347,6 @@ Mutex::~Mutex() {
errno = rc;
// TODO: should we just not log at all if shutting down? this could be the logging mutex!
MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_);
- Runtime* runtime = Runtime::Current();
- bool shutting_down = (runtime == NULL) || runtime->IsShuttingDownLocked();
PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_;
}
#endif
diff --git a/test/132-daemon-locks-shutdown/expected.txt b/test/132-daemon-locks-shutdown/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/132-daemon-locks-shutdown/expected.txt
diff --git a/test/132-daemon-locks-shutdown/info.txt b/test/132-daemon-locks-shutdown/info.txt
new file mode 100644
index 0000000..f804064
--- /dev/null
+++ b/test/132-daemon-locks-shutdown/info.txt
@@ -0,0 +1 @@
+Tests that we can shut down the runtime with daemons still looping over locks.
diff --git a/test/132-daemon-locks-shutdown/src/Main.java b/test/132-daemon-locks-shutdown/src/Main.java
new file mode 100644
index 0000000..b5bbc8c
--- /dev/null
+++ b/test/132-daemon-locks-shutdown/src/Main.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Test that daemon threads still contending for a lock don't make the runtime abort on shutdown.
+ */
+public class Main {
+
+ public final static int THREAD_COUNT = 32;
+
+ public static void main(String[] args) throws Exception {
+ Object sync = new Object();
+
+ for (int i = 0; i < THREAD_COUNT; i++) {
+ Thread t = new Thread(new Wait(sync));
+ t.setDaemon(true);
+ t.start();
+ }
+ }
+
+ private static class Wait implements Runnable {
+ private Object obj;
+
+ public Wait(Object obj) {
+ this.obj = obj;
+ }
+
+ public void run() {
+ for (;;) {
+ synchronized(obj) {
+ try {
+ obj.wait(1);
+ } catch (Exception exc) {
+ exc.printStackTrace(System.out);
+ }
+ }
+ }
+ }
+ }
+}