diff options
Diffstat (limited to 'openjdkjvmti/ti_thread.cc')
-rw-r--r-- | openjdkjvmti/ti_thread.cc | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc index 1082a9e771..99dea540e5 100644 --- a/openjdkjvmti/ti_thread.cc +++ b/openjdkjvmti/ti_thread.cc @@ -43,7 +43,7 @@ #include "mirror/class.h" #include "mirror/object-inl.h" #include "mirror/string.h" -#include "nativehelper/ScopedLocalRef.h" +#include "nativehelper/scoped_local_ref.h" #include "obj_ptr.h" #include "runtime.h" #include "runtime_callbacks.h" @@ -706,7 +706,7 @@ static void* AgentCallback(void* arg) { // We already have a peer. So call our special Attach function. art::Thread* self = art::Thread::Attach("JVMTI Agent thread", true, data->thread); - CHECK(self != nullptr); + CHECK(self != nullptr) << "threads_being_born_ should have ensured thread could be attached."; // The name in Attach() is only for logging. Set the thread name. This is important so // that the thread is no longer seen as starting up. { @@ -719,6 +719,13 @@ static void* AgentCallback(void* arg) { env->DeleteGlobalRef(data->thread); data->thread = nullptr; + { + // The StartThreadBirth was called in the parent thread. We let the runtime know we are up + // before going into the provided code. + art::MutexLock mu(art::Thread::Current(), *art::Locks::runtime_shutdown_lock_); + art::Runtime::Current()->EndThreadBirth(); + } + // Run the agent code. data->proc(data->jvmti_env, env, const_cast<void*>(data->arg)); @@ -748,6 +755,21 @@ jvmtiError ThreadUtil::RunAgentThread(jvmtiEnv* jvmti_env, return ERR(NULL_POINTER); } + { + art::Runtime* runtime = art::Runtime::Current(); + art::MutexLock mu(art::Thread::Current(), *art::Locks::runtime_shutdown_lock_); + if (runtime->IsShuttingDownLocked()) { + // The runtime is shutting down so we cannot create new threads. + // TODO It's not fully clear from the spec what we should do here. We aren't yet in + // JVMTI_PHASE_DEAD so we cannot return ERR(WRONG_PHASE) but creating new threads is now + // impossible. Existing agents don't seem to generally do anything with this return value so + // it doesn't matter too much. We could do something like sending a fake ThreadStart event + // even though code is never actually run. + return ERR(INTERNAL); + } + runtime->StartThreadBirth(); + } + std::unique_ptr<AgentData> data(new AgentData); data->arg = arg; data->proc = proc; @@ -759,10 +781,14 @@ jvmtiError ThreadUtil::RunAgentThread(jvmtiEnv* jvmti_env, pthread_t pthread; int pthread_create_result = pthread_create(&pthread, - nullptr, - &AgentCallback, - reinterpret_cast<void*>(data.get())); + nullptr, + &AgentCallback, + reinterpret_cast<void*>(data.get())); if (pthread_create_result != 0) { + // If the create succeeded the other thread will call EndThreadBirth. + art::Runtime* runtime = art::Runtime::Current(); + art::MutexLock mu(art::Thread::Current(), *art::Locks::runtime_shutdown_lock_); + runtime->EndThreadBirth(); return ERR(INTERNAL); } data.release(); |