summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2018-01-04 11:01:48 -0800
committer Alex Light <allight@google.com> 2018-01-04 18:19:36 -0800
commitb6f3464a934910e84e9a76e9f453bec71bffed5c (patch)
tree5b43e419a96763d272e8c034ea1489e1db99d64f
parent2f1ca4c99fe779a52bea32fab78fd6da59971eeb (diff)
Ensure shutdown thread has a java peer.
Using JVMTI it is possible to be running user-supplied code both on the shutdown thread and on other threads while the shutdown thread is running. Specifically some real-world JVMTI agents rely on being able to suspend the shutdown thread while they do cleanup work. In order to support this we will make sure that the shutdown thread is given its own java peer so it can be suspended by other threads. Bug: 66904725 Bug: 62821960 Test: ./test.py --host -j50 Change-Id: I1c89537c47fd3dd41aa4c0e7f7a6940d1c5ba913
-rw-r--r--runtime/runtime.cc7
-rw-r--r--test/901-hello-ti-agent/basics.cc8
-rw-r--r--test/980-redefine-object/expected.txt4
3 files changed, 16 insertions, 3 deletions
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 37ba9e473d..42f724ad4f 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -290,7 +290,12 @@ Runtime::~Runtime() {
Thread* self = Thread::Current();
const bool attach_shutdown_thread = self == nullptr;
if (attach_shutdown_thread) {
- CHECK(AttachCurrentThread("Shutdown thread", false, nullptr, false));
+ // We can only create a peer if the runtime is actually started. This is only not true during
+ // some tests.
+ CHECK(AttachCurrentThread("Shutdown thread",
+ false,
+ GetSystemThreadGroup(),
+ /* Create peer */IsStarted()));
self = Thread::Current();
} else {
LOG(WARNING) << "Current thread not detached in Runtime shutdown";
diff --git a/test/901-hello-ti-agent/basics.cc b/test/901-hello-ti-agent/basics.cc
index 472f2b768e..43a1d8319f 100644
--- a/test/901-hello-ti-agent/basics.cc
+++ b/test/901-hello-ti-agent/basics.cc
@@ -56,9 +56,13 @@ static void JNICALL VMInitCallback(jvmtiEnv *jvmti_env,
fsync(1);
}
-static void JNICALL VMDeatchCallback(jvmtiEnv *jenv, JNIEnv* jni_env ATTRIBUTE_UNUSED) {
+static void JNICALL VMDeathCallback(jvmtiEnv *jenv, JNIEnv* jni_env) {
printf("VMDeath (phase %d)\n", getPhase(jenv));
fsync(1);
+ jthread cur_thr;
+ CHECK_EQ(jenv->GetCurrentThread(&cur_thr), JVMTI_ERROR_NONE);
+ CHECK(cur_thr != nullptr);
+ jni_env->DeleteLocalRef(cur_thr);
}
@@ -67,7 +71,7 @@ static void InstallVMEvents(jvmtiEnv* env) {
memset(&callbacks, 0, sizeof(jvmtiEventCallbacks));
callbacks.VMStart = VMStartCallback;
callbacks.VMInit = VMInitCallback;
- callbacks.VMDeath = VMDeatchCallback;
+ callbacks.VMDeath = VMDeathCallback;
jvmtiError ret = env->SetEventCallbacks(&callbacks, sizeof(callbacks));
if (ret != JVMTI_ERROR_NONE) {
printf("Failed to install callbacks");
diff --git a/test/980-redefine-object/expected.txt b/test/980-redefine-object/expected.txt
index 4c294bc870..0a80882de1 100644
--- a/test/980-redefine-object/expected.txt
+++ b/test/980-redefine-object/expected.txt
@@ -30,3 +30,7 @@ Object allocated of type 'java.util.LinkedList$Node'
Object allocated of type 'java.lang.Exception'
Exception caught.
Finishing test!
+Object allocated of type 'java.lang.Thread'
+Object allocated of type 'java.lang.Object'
+Object allocated of type 'java.lang.Object'
+Object allocated of type 'java.security.AccessControlContext'