Implement JVMTI can_signal_thread capability.
Implements the JVMTI can_signal_thread capability and all associated
methods and behaviors. This includes both the StopThread and
InterruptThread functions.
This CL contains the tests for the previous CL.
Test: ./test.py --host -j50
Test: stress --cpu 59 && while ./test/run-test --host 1934; do; done
Bug: 62821960
Bug: 34415266
Change-Id: I7b6fc37da0d2673caa993e486f078cf129d74c0f
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index 907b515..9a809df 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -949,4 +949,65 @@
return OK;
}
+jvmtiError ThreadUtil::StopThread(jvmtiEnv* env ATTRIBUTE_UNUSED,
+ jthread thread,
+ jobject exception) {
+ art::Thread* self = art::Thread::Current();
+ art::ScopedObjectAccess soa(self);
+ art::StackHandleScope<1> hs(self);
+ if (exception == nullptr) {
+ return ERR(INVALID_OBJECT);
+ }
+ art::ObjPtr<art::mirror::Object> obj(soa.Decode<art::mirror::Object>(exception));
+ if (!obj->GetClass()->IsThrowableClass()) {
+ return ERR(INVALID_OBJECT);
+ }
+ art::Handle<art::mirror::Throwable> exc(hs.NewHandle(obj->AsThrowable()));
+ art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
+ art::Thread* target = nullptr;
+ jvmtiError err = ERR(INTERNAL);
+ if (!GetAliveNativeThread(thread, soa, &target, &err)) {
+ return err;
+ } else if (target->GetState() == art::ThreadState::kStarting || target->IsStillStarting()) {
+ return ERR(THREAD_NOT_ALIVE);
+ }
+ struct StopThreadClosure : public art::Closure {
+ public:
+ explicit StopThreadClosure(art::Handle<art::mirror::Throwable> except) : exception_(except) { }
+
+ void Run(art::Thread* me) REQUIRES_SHARED(art::Locks::mutator_lock_) {
+ // Make sure the thread is prepared to notice the exception.
+ art::Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(me);
+ me->SetAsyncException(exception_.Get());
+ // Wake up the thread if it is sleeping.
+ me->Notify();
+ }
+
+ private:
+ art::Handle<art::mirror::Throwable> exception_;
+ };
+ StopThreadClosure c(exc);
+ if (target->RequestSynchronousCheckpoint(&c)) {
+ return OK;
+ } else {
+ // Something went wrong, probably the thread died.
+ return ERR(THREAD_NOT_ALIVE);
+ }
+}
+
+jvmtiError ThreadUtil::InterruptThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread thread) {
+ art::Thread* self = art::Thread::Current();
+ art::ScopedObjectAccess soa(self);
+ art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
+ art::Thread* target = nullptr;
+ jvmtiError err = ERR(INTERNAL);
+ if (!GetAliveNativeThread(thread, soa, &target, &err)) {
+ return err;
+ } else if (target->GetState() == art::ThreadState::kStarting || target->IsStillStarting()) {
+ return ERR(THREAD_NOT_ALIVE);
+ }
+ target->Interrupt(self);
+ return OK;
+}
+
} // namespace openjdkjvmti