diff options
author | 2018-01-04 11:01:48 -0800 | |
---|---|---|
committer | 2018-01-04 18:19:36 -0800 | |
commit | b6f3464a934910e84e9a76e9f453bec71bffed5c (patch) | |
tree | 5b43e419a96763d272e8c034ea1489e1db99d64f | |
parent | 2f1ca4c99fe779a52bea32fab78fd6da59971eeb (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.cc | 7 | ||||
-rw-r--r-- | test/901-hello-ti-agent/basics.cc | 8 | ||||
-rw-r--r-- | test/980-redefine-object/expected.txt | 4 |
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' |