• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "runtime_callbacks.h"
18 
19 #include <signal.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include <initializer_list>
24 #include <memory>
25 #include <mutex>
26 #include <string>
27 
28 #include "jni.h"
29 
30 #include "art_method-inl.h"
31 #include "base/mem_map.h"
32 #include "base/mutex.h"
33 #include "class_linker.h"
34 #include "common_runtime_test.h"
35 #include "dex/class_reference.h"
36 #include "handle.h"
37 #include "handle_scope-inl.h"
38 #include "mirror/class-inl.h"
39 #include "mirror/class_loader.h"
40 #include "monitor-inl.h"
41 #include "nativehelper/scoped_local_ref.h"
42 #include "obj_ptr-inl.h"
43 #include "runtime.h"
44 #include "scoped_thread_state_change-inl.h"
45 #include "thread-inl.h"
46 #include "thread_list.h"
47 #include "well_known_classes.h"
48 
49 namespace art {
50 
51 class RuntimeCallbacksTest : public CommonRuntimeTest {
52  protected:
SetUp()53   void SetUp() override {
54     CommonRuntimeTest::SetUp();
55 
56     Thread* self = Thread::Current();
57     ScopedObjectAccess soa(self);
58     ScopedThreadSuspension sts(self, ThreadState::kWaitingForDebuggerToAttach);
59     ScopedSuspendAll ssa("RuntimeCallbacksTest SetUp");
60     AddListener();
61   }
62 
TearDown()63   void TearDown() override {
64     {
65       Thread* self = Thread::Current();
66       ScopedObjectAccess soa(self);
67       ScopedThreadSuspension sts(self, ThreadState::kWaitingForDebuggerToAttach);
68       ScopedSuspendAll ssa("RuntimeCallbacksTest TearDown");
69       RemoveListener();
70     }
71 
72     CommonRuntimeTest::TearDown();
73   }
74 
75   virtual void AddListener() REQUIRES(Locks::mutator_lock_) = 0;
76   virtual void RemoveListener() REQUIRES(Locks::mutator_lock_) = 0;
77 
MakeExecutable(ObjPtr<mirror::Class> klass)78   void MakeExecutable(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
79     CHECK(klass != nullptr);
80     PointerSize pointer_size = class_linker_->GetImagePointerSize();
81     for (auto& m : klass->GetMethods(pointer_size)) {
82       if (!m.IsAbstract()) {
83         Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
84       }
85     }
86   }
87 };
88 
89 class ThreadLifecycleCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
90  public:
PthreadsCallback(void * arg ATTRIBUTE_UNUSED)91   static void* PthreadsCallback(void* arg ATTRIBUTE_UNUSED) {
92     // Attach.
93     Runtime* runtime = Runtime::Current();
94     CHECK(runtime->AttachCurrentThread("ThreadLifecycle test thread", true, nullptr, false));
95 
96     // Detach.
97     runtime->DetachCurrentThread();
98 
99     // Die...
100     return nullptr;
101   }
102 
103  protected:
AddListener()104   void AddListener() override REQUIRES(Locks::mutator_lock_) {
105     Runtime::Current()->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&cb_);
106   }
RemoveListener()107   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
108     Runtime::Current()->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&cb_);
109   }
110 
111   enum CallbackState {
112     kBase,
113     kStarted,
114     kDied,
115     kWrongStart,
116     kWrongDeath,
117   };
118 
119   struct Callback : public ThreadLifecycleCallback {
ThreadStartart::ThreadLifecycleCallbackRuntimeCallbacksTest::Callback120     void ThreadStart(Thread* self) override {
121       {
122         ScopedObjectAccess soa(self);
123         LOG(DEBUG) << "ThreadStart callback for thread: " << self->GetThreadName();
124       }
125       if (state == CallbackState::kBase) {
126         state = CallbackState::kStarted;
127         stored_self = self;
128       } else {
129         state = CallbackState::kWrongStart;
130       }
131     }
132 
ThreadDeathart::ThreadLifecycleCallbackRuntimeCallbacksTest::Callback133     void ThreadDeath(Thread* self) override {
134       {
135         ScopedObjectAccess soa(self);
136         LOG(DEBUG) << "ThreadDeath callback for thread: " << self->GetThreadName();
137       }
138       if (state == CallbackState::kStarted && self == stored_self) {
139         state = CallbackState::kDied;
140       } else {
141         state = CallbackState::kWrongDeath;
142       }
143     }
144 
145     Thread* stored_self;
146     CallbackState state = CallbackState::kBase;
147   };
148 
149   Callback cb_;
150 };
151 
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackJava)152 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackJava) {
153   Thread* self = Thread::Current();
154 
155   self->TransitionFromSuspendedToRunnable();
156   bool started = runtime_->Start();
157   ASSERT_TRUE(started);
158   // Make sure the workers are done starting so we don't get callbacks for them.
159   runtime_->WaitForThreadPoolWorkersToStart();
160 
161   // The metrics reporting thread will sometimes be slow to start. Synchronously requesting a
162   // metrics report forces us to wait until the thread has started.
163   runtime_->RequestMetricsReport(/*synchronous=*/true);
164 
165   cb_.state = CallbackState::kBase;  // Ignore main thread attach.
166 
167   {
168     ScopedObjectAccess soa(self);
169     MakeExecutable(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread));
170   }
171 
172   JNIEnv* env = self->GetJniEnv();
173 
174   ScopedLocalRef<jobject> thread_name(env,
175                                       env->NewStringUTF("ThreadLifecycleCallback test thread"));
176   ASSERT_TRUE(thread_name.get() != nullptr);
177 
178   ScopedLocalRef<jobject> thread(env, env->AllocObject(WellKnownClasses::java_lang_Thread));
179   ASSERT_TRUE(thread.get() != nullptr);
180 
181   env->CallNonvirtualVoidMethod(thread.get(),
182                                 WellKnownClasses::java_lang_Thread,
183                                 WellKnownClasses::java_lang_Thread_init,
184                                 runtime_->GetMainThreadGroup(),
185                                 thread_name.get(),
186                                 kMinThreadPriority,
187                                 JNI_FALSE);
188   ASSERT_FALSE(env->ExceptionCheck());
189 
190   jmethodID start_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "start", "()V");
191   ASSERT_TRUE(start_id != nullptr);
192 
193   env->CallVoidMethod(thread.get(), start_id);
194   ASSERT_FALSE(env->ExceptionCheck());
195 
196   jmethodID join_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "join", "()V");
197   ASSERT_TRUE(join_id != nullptr);
198 
199   env->CallVoidMethod(thread.get(), join_id);
200   ASSERT_FALSE(env->ExceptionCheck());
201 
202   EXPECT_EQ(cb_.state, CallbackState::kDied);
203 }
204 
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackAttach)205 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
206   std::string error_msg;
207   MemMap stack = MemMap::MapAnonymous("ThreadLifecycleCallback Thread",
208                                       128 * kPageSize,  // Just some small stack.
209                                       PROT_READ | PROT_WRITE,
210                                       /*low_4gb=*/ false,
211                                       &error_msg);
212   ASSERT_TRUE(stack.IsValid()) << error_msg;
213 
214   const char* reason = "ThreadLifecycleCallback test thread";
215   pthread_attr_t attr;
216   CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
217   CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack.Begin(), stack.Size()), reason);
218   pthread_t pthread;
219   CHECK_PTHREAD_CALL(pthread_create,
220                      (&pthread,
221                          &attr,
222                          &ThreadLifecycleCallbackRuntimeCallbacksTest::PthreadsCallback,
223                          this),
224                          reason);
225   CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
226 
227   CHECK_PTHREAD_CALL(pthread_join, (pthread, nullptr), "ThreadLifecycleCallback test shutdown");
228 
229   // Detach is not a ThreadDeath event, so we expect to be in state Started.
230   EXPECT_TRUE(cb_.state == CallbackState::kStarted) << static_cast<int>(cb_.state);
231 }
232 
233 class ClassLoadCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
234  protected:
AddListener()235   void AddListener() override REQUIRES(Locks::mutator_lock_) {
236     Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&cb_);
237   }
RemoveListener()238   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
239     Runtime::Current()->GetRuntimeCallbacks()->RemoveClassLoadCallback(&cb_);
240   }
241 
Expect(std::initializer_list<const char * > list)242   bool Expect(std::initializer_list<const char*> list) {
243     if (cb_.data.size() != list.size()) {
244       PrintError(list);
245       return false;
246     }
247 
248     if (!std::equal(cb_.data.begin(), cb_.data.end(), list.begin())) {
249       PrintError(list);
250       return false;
251     }
252 
253     return true;
254   }
255 
PrintError(std::initializer_list<const char * > list)256   void PrintError(std::initializer_list<const char*> list) {
257     LOG(ERROR) << "Expected:";
258     for (const char* expected : list) {
259       LOG(ERROR) << "  " << expected;
260     }
261     LOG(ERROR) << "Found:";
262     for (const auto& s : cb_.data) {
263       LOG(ERROR) << "  " << s;
264     }
265   }
266 
267   struct Callback : public ClassLoadCallback {
ClassPreDefineart::ClassLoadCallbackRuntimeCallbacksTest::Callback268     void ClassPreDefine(const char* descriptor,
269                         Handle<mirror::Class> klass ATTRIBUTE_UNUSED,
270                         Handle<mirror::ClassLoader> class_loader ATTRIBUTE_UNUSED,
271                         const DexFile& initial_dex_file,
272                         const dex::ClassDef& initial_class_def ATTRIBUTE_UNUSED,
273                         /*out*/DexFile const** final_dex_file ATTRIBUTE_UNUSED,
274                         /*out*/dex::ClassDef const** final_class_def ATTRIBUTE_UNUSED) override
275         REQUIRES_SHARED(Locks::mutator_lock_) {
276       const std::string& location = initial_dex_file.GetLocation();
277       std::string event =
278           std::string("PreDefine:") + descriptor + " <" +
279           location.substr(location.rfind('/') + 1, location.size()) + ">";
280       data.push_back(event);
281     }
282 
ClassLoadart::ClassLoadCallbackRuntimeCallbacksTest::Callback283     void ClassLoad(Handle<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
284       std::string tmp;
285       std::string event = std::string("Load:") + klass->GetDescriptor(&tmp);
286       data.push_back(event);
287     }
288 
ClassPrepareart::ClassLoadCallbackRuntimeCallbacksTest::Callback289     void ClassPrepare(Handle<mirror::Class> temp_klass,
290                       Handle<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
291       std::string tmp, tmp2;
292       std::string event = std::string("Prepare:") + klass->GetDescriptor(&tmp)
293           + "[" + temp_klass->GetDescriptor(&tmp2) + "]";
294       data.push_back(event);
295     }
296 
297     std::vector<std::string> data;
298   };
299 
300   Callback cb_;
301 };
302 
TEST_F(ClassLoadCallbackRuntimeCallbacksTest,ClassLoadCallback)303 TEST_F(ClassLoadCallbackRuntimeCallbacksTest, ClassLoadCallback) {
304   ScopedObjectAccess soa(Thread::Current());
305   jobject jclass_loader = LoadDex("XandY");
306   VariableSizedHandleScope hs(soa.Self());
307   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
308       soa.Decode<mirror::ClassLoader>(jclass_loader)));
309 
310   const char* descriptor_y = "LY;";
311   Handle<mirror::Class> h_Y(
312       hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader)));
313   ASSERT_TRUE(h_Y != nullptr);
314 
315   bool expect1 = Expect({ "PreDefine:LY; <art-gtest-jars-XandY.jar>",
316                           "PreDefine:LX; <art-gtest-jars-XandY.jar>",
317                           "Load:LX;",
318                           "Prepare:LX;[LX;]",
319                           "Load:LY;",
320                           "Prepare:LY;[LY;]" });
321   EXPECT_TRUE(expect1);
322 
323   cb_.data.clear();
324 
325   ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true));
326 
327   bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-jars-XandY.jar>",
328                           "Load:LY$Z;",
329                           "Prepare:LY$Z;[LY$Z;]" });
330   EXPECT_TRUE(expect2);
331 }
332 
333 class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
334  protected:
AddListener()335   void AddListener() override REQUIRES(Locks::mutator_lock_) {
336     Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&cb_);
337   }
RemoveListener()338   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
339     Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&cb_);
340   }
341 
342   struct Callback : public RuntimeSigQuitCallback {
SigQuitart::RuntimeSigQuitCallbackRuntimeCallbacksTest::Callback343     void SigQuit() override {
344       ++sigquit_count;
345     }
346 
347     size_t sigquit_count = 0;
348   };
349 
350   Callback cb_;
351 };
352 
TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest,SigQuit)353 TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) {
354   // The runtime needs to be started for the signal handler.
355   Thread* self = Thread::Current();
356 
357   self->TransitionFromSuspendedToRunnable();
358   bool started = runtime_->Start();
359   ASSERT_TRUE(started);
360 
361   EXPECT_EQ(0u, cb_.sigquit_count);
362 
363   kill(getpid(), SIGQUIT);
364 
365   // Try a few times.
366   for (size_t i = 0; i != 30; ++i) {
367     if (cb_.sigquit_count == 0) {
368       sleep(1);
369     } else {
370       break;
371     }
372   }
373   EXPECT_EQ(1u, cb_.sigquit_count);
374 }
375 
376 class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
377  protected:
AddListener()378   void AddListener() override REQUIRES(Locks::mutator_lock_) {
379     Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_);
380   }
RemoveListener()381   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
382     Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_);
383   }
384 
TearDown()385   void TearDown() override {
386     // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone.
387     CommonRuntimeTest::TearDown();
388   }
389 
390   struct Callback : public RuntimePhaseCallback {
NextRuntimePhaseart::RuntimePhaseCallbackRuntimeCallbacksTest::Callback391     void NextRuntimePhase(RuntimePhaseCallback::RuntimePhase p) override {
392       if (p == RuntimePhaseCallback::RuntimePhase::kInitialAgents) {
393         if (start_seen > 0 || init_seen > 0 || death_seen > 0) {
394           LOG(FATAL) << "Unexpected order";
395         }
396         ++initial_agents_seen;
397       } else if (p == RuntimePhaseCallback::RuntimePhase::kStart) {
398         if (init_seen > 0 || death_seen > 0) {
399           LOG(FATAL) << "Init seen before start.";
400         }
401         ++start_seen;
402       } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) {
403         ++init_seen;
404       } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) {
405         ++death_seen;
406       } else {
407         LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p);
408       }
409     }
410 
411     size_t initial_agents_seen = 0;
412     size_t start_seen = 0;
413     size_t init_seen = 0;
414     size_t death_seen = 0;
415   };
416 
417   Callback cb_;
418 };
419 
TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest,Phases)420 TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest, Phases) {
421   ASSERT_EQ(0u, cb_.initial_agents_seen);
422   ASSERT_EQ(0u, cb_.start_seen);
423   ASSERT_EQ(0u, cb_.init_seen);
424   ASSERT_EQ(0u, cb_.death_seen);
425 
426   // Start the runtime.
427   {
428     Thread* self = Thread::Current();
429     self->TransitionFromSuspendedToRunnable();
430     bool started = runtime_->Start();
431     ASSERT_TRUE(started);
432   }
433 
434   ASSERT_EQ(0u, cb_.initial_agents_seen);
435   ASSERT_EQ(1u, cb_.start_seen);
436   ASSERT_EQ(1u, cb_.init_seen);
437   ASSERT_EQ(0u, cb_.death_seen);
438 
439   // Delete the runtime.
440   runtime_.reset();
441 
442   ASSERT_EQ(0u, cb_.initial_agents_seen);
443   ASSERT_EQ(1u, cb_.start_seen);
444   ASSERT_EQ(1u, cb_.init_seen);
445   ASSERT_EQ(1u, cb_.death_seen);
446 }
447 
448 class MonitorWaitCallbacksTest : public RuntimeCallbacksTest {
449  protected:
AddListener()450   void AddListener() override REQUIRES(Locks::mutator_lock_) {
451     Runtime::Current()->GetRuntimeCallbacks()->AddMonitorCallback(&cb_);
452   }
RemoveListener()453   void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
454     Runtime::Current()->GetRuntimeCallbacks()->RemoveMonitorCallback(&cb_);
455   }
456 
457   struct Callback : public MonitorCallback {
IsInterestingObjectart::MonitorWaitCallbacksTest::Callback458     bool IsInterestingObject(ObjPtr<mirror::Object> obj)
459         REQUIRES_SHARED(art::Locks::mutator_lock_) {
460       if (!obj->IsClass()) {
461         return false;
462       }
463       std::lock_guard<std::mutex> lock(ref_guard_);
464       ObjPtr<mirror::Class> k = obj->AsClass();
465       ClassReference test = { &k->GetDexFile(), k->GetDexClassDefIndex() };
466       return ref_ == test;
467     }
468 
SetInterestingObjectart::MonitorWaitCallbacksTest::Callback469     void SetInterestingObject(ObjPtr<mirror::Object> obj)
470         REQUIRES_SHARED(art::Locks::mutator_lock_) {
471       std::lock_guard<std::mutex> lock(ref_guard_);
472       ObjPtr<mirror::Class> k = obj->AsClass();
473       ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() };
474     }
475 
MonitorContendedLockingart::MonitorWaitCallbacksTest::Callback476     void MonitorContendedLocking(Monitor* mon ATTRIBUTE_UNUSED) override
477         REQUIRES_SHARED(Locks::mutator_lock_) { }
478 
MonitorContendedLockedart::MonitorWaitCallbacksTest::Callback479     void MonitorContendedLocked(Monitor* mon ATTRIBUTE_UNUSED) override
480         REQUIRES_SHARED(Locks::mutator_lock_) { }
481 
ObjectWaitStartart::MonitorWaitCallbacksTest::Callback482     void ObjectWaitStart(Handle<mirror::Object> obj, int64_t millis ATTRIBUTE_UNUSED) override
483         REQUIRES_SHARED(Locks::mutator_lock_) {
484       if (IsInterestingObject(obj.Get())) {
485         saw_wait_start_ = true;
486       }
487     }
488 
MonitorWaitFinishedart::MonitorWaitCallbacksTest::Callback489     void MonitorWaitFinished(Monitor* m, bool timed_out ATTRIBUTE_UNUSED) override
490         REQUIRES_SHARED(Locks::mutator_lock_) {
491       if (IsInterestingObject(m->GetObject())) {
492         saw_wait_finished_ = true;
493       }
494     }
495 
496     std::mutex ref_guard_;
497     ClassReference ref_ = {nullptr, 0};
498     bool saw_wait_start_ = false;
499     bool saw_wait_finished_ = false;
500   };
501 
502   Callback cb_;
503 };
504 
505 // TODO It would be good to have more tests for this but due to the multi-threaded nature of the
506 // callbacks this is difficult. For now the run-tests 1931 & 1932 should be sufficient.
TEST_F(MonitorWaitCallbacksTest,WaitUnlocked)507 TEST_F(MonitorWaitCallbacksTest, WaitUnlocked) {
508   ASSERT_FALSE(cb_.saw_wait_finished_);
509   ASSERT_FALSE(cb_.saw_wait_start_);
510   {
511     Thread* self = Thread::Current();
512     self->TransitionFromSuspendedToRunnable();
513     bool started = runtime_->Start();
514     ASSERT_TRUE(started);
515     {
516       ScopedObjectAccess soa(self);
517       cb_.SetInterestingObject(
518           soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections));
519       Monitor::Wait(
520           self,
521           // Just a random class
522           soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections),
523           /*ms=*/0,
524           /*ns=*/0,
525           /*interruptShouldThrow=*/false,
526           /*why=*/ThreadState::kWaiting);
527     }
528   }
529   ASSERT_TRUE(cb_.saw_wait_start_);
530   ASSERT_FALSE(cb_.saw_wait_finished_);
531 }
532 
533 }  // namespace art
534