• 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/mutex.h"
32 #include "class_linker.h"
33 #include "common_runtime_test.h"
34 #include "dex/class_reference.h"
35 #include "handle.h"
36 #include "handle_scope-inl.h"
37 #include "mem_map.h"
38 #include "mirror/class-inl.h"
39 #include "mirror/class_loader.h"
40 #include "monitor.h"
41 #include "nativehelper/scoped_local_ref.h"
42 #include "obj_ptr.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, 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, 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         class_linker_->SetEntryPointsToInterpreter(&m);
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       if (state == CallbackState::kBase) {
122         state = CallbackState::kStarted;
123         stored_self = self;
124       } else {
125         state = CallbackState::kWrongStart;
126       }
127     }
128 
ThreadDeathart::ThreadLifecycleCallbackRuntimeCallbacksTest::Callback129     void ThreadDeath(Thread* self) OVERRIDE {
130       if (state == CallbackState::kStarted && self == stored_self) {
131         state = CallbackState::kDied;
132       } else {
133         state = CallbackState::kWrongDeath;
134       }
135     }
136 
137     Thread* stored_self;
138     CallbackState state = CallbackState::kBase;
139   };
140 
141   Callback cb_;
142 };
143 
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackJava)144 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackJava) {
145   Thread* self = Thread::Current();
146 
147   self->TransitionFromSuspendedToRunnable();
148   bool started = runtime_->Start();
149   ASSERT_TRUE(started);
150 
151   cb_.state = CallbackState::kBase;  // Ignore main thread attach.
152 
153   {
154     ScopedObjectAccess soa(self);
155     MakeExecutable(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread));
156   }
157 
158   JNIEnv* env = self->GetJniEnv();
159 
160   ScopedLocalRef<jobject> thread_name(env,
161                                       env->NewStringUTF("ThreadLifecycleCallback test thread"));
162   ASSERT_TRUE(thread_name.get() != nullptr);
163 
164   ScopedLocalRef<jobject> thread(env, env->AllocObject(WellKnownClasses::java_lang_Thread));
165   ASSERT_TRUE(thread.get() != nullptr);
166 
167   env->CallNonvirtualVoidMethod(thread.get(),
168                                 WellKnownClasses::java_lang_Thread,
169                                 WellKnownClasses::java_lang_Thread_init,
170                                 runtime_->GetMainThreadGroup(),
171                                 thread_name.get(),
172                                 kMinThreadPriority,
173                                 JNI_FALSE);
174   ASSERT_FALSE(env->ExceptionCheck());
175 
176   jmethodID start_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "start", "()V");
177   ASSERT_TRUE(start_id != nullptr);
178 
179   env->CallVoidMethod(thread.get(), start_id);
180   ASSERT_FALSE(env->ExceptionCheck());
181 
182   jmethodID join_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "join", "()V");
183   ASSERT_TRUE(join_id != nullptr);
184 
185   env->CallVoidMethod(thread.get(), join_id);
186   ASSERT_FALSE(env->ExceptionCheck());
187 
188   EXPECT_TRUE(cb_.state == CallbackState::kDied) << static_cast<int>(cb_.state);
189 }
190 
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackAttach)191 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
192   std::string error_msg;
193   std::unique_ptr<MemMap> stack(MemMap::MapAnonymous("ThreadLifecycleCallback Thread",
194                                                      nullptr,
195                                                      128 * kPageSize,  // Just some small stack.
196                                                      PROT_READ | PROT_WRITE,
197                                                      false,
198                                                      false,
199                                                      &error_msg));
200   ASSERT_FALSE(stack == nullptr) << error_msg;
201 
202   const char* reason = "ThreadLifecycleCallback test thread";
203   pthread_attr_t attr;
204   CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
205   CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack->Begin(), stack->Size()), reason);
206   pthread_t pthread;
207   CHECK_PTHREAD_CALL(pthread_create,
208                      (&pthread,
209                          &attr,
210                          &ThreadLifecycleCallbackRuntimeCallbacksTest::PthreadsCallback,
211                          this),
212                          reason);
213   CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
214 
215   CHECK_PTHREAD_CALL(pthread_join, (pthread, nullptr), "ThreadLifecycleCallback test shutdown");
216 
217   // Detach is not a ThreadDeath event, so we expect to be in state Started.
218   EXPECT_TRUE(cb_.state == CallbackState::kStarted) << static_cast<int>(cb_.state);
219 }
220 
221 class ClassLoadCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
222  protected:
AddListener()223   void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
224     Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&cb_);
225   }
RemoveListener()226   void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
227     Runtime::Current()->GetRuntimeCallbacks()->RemoveClassLoadCallback(&cb_);
228   }
229 
Expect(std::initializer_list<const char * > list)230   bool Expect(std::initializer_list<const char*> list) {
231     if (cb_.data.size() != list.size()) {
232       PrintError(list);
233       return false;
234     }
235 
236     if (!std::equal(cb_.data.begin(), cb_.data.end(), list.begin())) {
237       PrintError(list);
238       return false;
239     }
240 
241     return true;
242   }
243 
PrintError(std::initializer_list<const char * > list)244   void PrintError(std::initializer_list<const char*> list) {
245     LOG(ERROR) << "Expected:";
246     for (const char* expected : list) {
247       LOG(ERROR) << "  " << expected;
248     }
249     LOG(ERROR) << "Found:";
250     for (const auto& s : cb_.data) {
251       LOG(ERROR) << "  " << s;
252     }
253   }
254 
255   struct Callback : public ClassLoadCallback {
ClassPreDefineart::ClassLoadCallbackRuntimeCallbacksTest::Callback256     virtual void ClassPreDefine(const char* descriptor,
257                                 Handle<mirror::Class> klass ATTRIBUTE_UNUSED,
258                                 Handle<mirror::ClassLoader> class_loader ATTRIBUTE_UNUSED,
259                                 const DexFile& initial_dex_file,
260                                 const DexFile::ClassDef& initial_class_def ATTRIBUTE_UNUSED,
261                                 /*out*/DexFile const** final_dex_file ATTRIBUTE_UNUSED,
262                                 /*out*/DexFile::ClassDef const** final_class_def ATTRIBUTE_UNUSED)
263         OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
264       const std::string& location = initial_dex_file.GetLocation();
265       std::string event =
266           std::string("PreDefine:") + descriptor + " <" +
267           location.substr(location.rfind('/') + 1, location.size()) + ">";
268       data.push_back(event);
269     }
270 
ClassLoadart::ClassLoadCallbackRuntimeCallbacksTest::Callback271     void ClassLoad(Handle<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
272       std::string tmp;
273       std::string event = std::string("Load:") + klass->GetDescriptor(&tmp);
274       data.push_back(event);
275     }
276 
ClassPrepareart::ClassLoadCallbackRuntimeCallbacksTest::Callback277     void ClassPrepare(Handle<mirror::Class> temp_klass,
278                       Handle<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
279       std::string tmp, tmp2;
280       std::string event = std::string("Prepare:") + klass->GetDescriptor(&tmp)
281           + "[" + temp_klass->GetDescriptor(&tmp2) + "]";
282       data.push_back(event);
283     }
284 
285     std::vector<std::string> data;
286   };
287 
288   Callback cb_;
289 };
290 
TEST_F(ClassLoadCallbackRuntimeCallbacksTest,ClassLoadCallback)291 TEST_F(ClassLoadCallbackRuntimeCallbacksTest, ClassLoadCallback) {
292   ScopedObjectAccess soa(Thread::Current());
293   jobject jclass_loader = LoadDex("XandY");
294   VariableSizedHandleScope hs(soa.Self());
295   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
296       soa.Decode<mirror::ClassLoader>(jclass_loader)));
297 
298   const char* descriptor_y = "LY;";
299   Handle<mirror::Class> h_Y(
300       hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader)));
301   ASSERT_TRUE(h_Y != nullptr);
302 
303   bool expect1 = Expect({ "PreDefine:LY; <art-gtest-XandY.jar>",
304                           "PreDefine:LX; <art-gtest-XandY.jar>",
305                           "Load:LX;",
306                           "Prepare:LX;[LX;]",
307                           "Load:LY;",
308                           "Prepare:LY;[LY;]" });
309   EXPECT_TRUE(expect1);
310 
311   cb_.data.clear();
312 
313   ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true));
314 
315   bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-XandY.jar>",
316                           "Load:LY$Z;",
317                           "Prepare:LY$Z;[LY$Z;]" });
318   EXPECT_TRUE(expect2);
319 }
320 
321 class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
322  protected:
AddListener()323   void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
324     Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&cb_);
325   }
RemoveListener()326   void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
327     Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&cb_);
328   }
329 
330   struct Callback : public RuntimeSigQuitCallback {
SigQuitart::RuntimeSigQuitCallbackRuntimeCallbacksTest::Callback331     void SigQuit() OVERRIDE {
332       ++sigquit_count;
333     }
334 
335     size_t sigquit_count = 0;
336   };
337 
338   Callback cb_;
339 };
340 
TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest,SigQuit)341 TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) {
342   // SigQuit induces a dump. ASAN isn't happy with libunwind reading memory.
343   TEST_DISABLED_FOR_MEMORY_TOOL_ASAN();
344 
345   // The runtime needs to be started for the signal handler.
346   Thread* self = Thread::Current();
347 
348   self->TransitionFromSuspendedToRunnable();
349   bool started = runtime_->Start();
350   ASSERT_TRUE(started);
351 
352   EXPECT_EQ(0u, cb_.sigquit_count);
353 
354   kill(getpid(), SIGQUIT);
355 
356   // Try a few times.
357   for (size_t i = 0; i != 30; ++i) {
358     if (cb_.sigquit_count == 0) {
359       sleep(1);
360     } else {
361       break;
362     }
363   }
364   EXPECT_EQ(1u, cb_.sigquit_count);
365 }
366 
367 class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
368  protected:
AddListener()369   void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
370     Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_);
371   }
RemoveListener()372   void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
373     Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_);
374   }
375 
TearDown()376   void TearDown() OVERRIDE {
377     // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone.
378     CommonRuntimeTest::TearDown();
379   }
380 
381   struct Callback : public RuntimePhaseCallback {
NextRuntimePhaseart::RuntimePhaseCallbackRuntimeCallbacksTest::Callback382     void NextRuntimePhase(RuntimePhaseCallback::RuntimePhase p) OVERRIDE {
383       if (p == RuntimePhaseCallback::RuntimePhase::kInitialAgents) {
384         if (start_seen > 0 || init_seen > 0 || death_seen > 0) {
385           LOG(FATAL) << "Unexpected order";
386         }
387         ++initial_agents_seen;
388       } else if (p == RuntimePhaseCallback::RuntimePhase::kStart) {
389         if (init_seen > 0 || death_seen > 0) {
390           LOG(FATAL) << "Init seen before start.";
391         }
392         ++start_seen;
393       } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) {
394         ++init_seen;
395       } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) {
396         ++death_seen;
397       } else {
398         LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p);
399       }
400     }
401 
402     size_t initial_agents_seen = 0;
403     size_t start_seen = 0;
404     size_t init_seen = 0;
405     size_t death_seen = 0;
406   };
407 
408   Callback cb_;
409 };
410 
TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest,Phases)411 TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest, Phases) {
412   ASSERT_EQ(0u, cb_.initial_agents_seen);
413   ASSERT_EQ(0u, cb_.start_seen);
414   ASSERT_EQ(0u, cb_.init_seen);
415   ASSERT_EQ(0u, cb_.death_seen);
416 
417   // Start the runtime.
418   {
419     Thread* self = Thread::Current();
420     self->TransitionFromSuspendedToRunnable();
421     bool started = runtime_->Start();
422     ASSERT_TRUE(started);
423   }
424 
425   ASSERT_EQ(0u, cb_.initial_agents_seen);
426   ASSERT_EQ(1u, cb_.start_seen);
427   ASSERT_EQ(1u, cb_.init_seen);
428   ASSERT_EQ(0u, cb_.death_seen);
429 
430   // Delete the runtime.
431   runtime_.reset();
432 
433   ASSERT_EQ(0u, cb_.initial_agents_seen);
434   ASSERT_EQ(1u, cb_.start_seen);
435   ASSERT_EQ(1u, cb_.init_seen);
436   ASSERT_EQ(1u, cb_.death_seen);
437 }
438 
439 class MonitorWaitCallbacksTest : public RuntimeCallbacksTest {
440  protected:
AddListener()441   void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
442     Runtime::Current()->GetRuntimeCallbacks()->AddMonitorCallback(&cb_);
443   }
RemoveListener()444   void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) {
445     Runtime::Current()->GetRuntimeCallbacks()->RemoveMonitorCallback(&cb_);
446   }
447 
448   struct Callback : public MonitorCallback {
IsInterestingObjectart::MonitorWaitCallbacksTest::Callback449     bool IsInterestingObject(mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
450       if (!obj->IsClass()) {
451         return false;
452       }
453       std::lock_guard<std::mutex> lock(ref_guard_);
454       mirror::Class* k = obj->AsClass();
455       ClassReference test = { &k->GetDexFile(), k->GetDexClassDefIndex() };
456       return ref_ == test;
457     }
458 
SetInterestingObjectart::MonitorWaitCallbacksTest::Callback459     void SetInterestingObject(mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
460       std::lock_guard<std::mutex> lock(ref_guard_);
461       mirror::Class* k = obj->AsClass();
462       ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() };
463     }
464 
MonitorContendedLockingart::MonitorWaitCallbacksTest::Callback465     void MonitorContendedLocking(Monitor* mon ATTRIBUTE_UNUSED)
466         REQUIRES_SHARED(Locks::mutator_lock_) { }
467 
MonitorContendedLockedart::MonitorWaitCallbacksTest::Callback468     void MonitorContendedLocked(Monitor* mon ATTRIBUTE_UNUSED)
469         REQUIRES_SHARED(Locks::mutator_lock_) { }
470 
ObjectWaitStartart::MonitorWaitCallbacksTest::Callback471     void ObjectWaitStart(Handle<mirror::Object> obj, int64_t millis ATTRIBUTE_UNUSED)
472         REQUIRES_SHARED(Locks::mutator_lock_) {
473       if (IsInterestingObject(obj.Get())) {
474         saw_wait_start_ = true;
475       }
476     }
477 
MonitorWaitFinishedart::MonitorWaitCallbacksTest::Callback478     void MonitorWaitFinished(Monitor* m, bool timed_out ATTRIBUTE_UNUSED)
479         REQUIRES_SHARED(Locks::mutator_lock_) {
480       if (IsInterestingObject(m->GetObject())) {
481         saw_wait_finished_ = true;
482       }
483     }
484 
485     std::mutex ref_guard_;
486     ClassReference ref_ = {nullptr, 0};
487     bool saw_wait_start_ = false;
488     bool saw_wait_finished_ = false;
489   };
490 
491   Callback cb_;
492 };
493 
494 // TODO It would be good to have more tests for this but due to the multi-threaded nature of the
495 // callbacks this is difficult. For now the run-tests 1931 & 1932 should be sufficient.
TEST_F(MonitorWaitCallbacksTest,WaitUnlocked)496 TEST_F(MonitorWaitCallbacksTest, WaitUnlocked) {
497   ASSERT_FALSE(cb_.saw_wait_finished_);
498   ASSERT_FALSE(cb_.saw_wait_start_);
499   {
500     Thread* self = Thread::Current();
501     self->TransitionFromSuspendedToRunnable();
502     bool started = runtime_->Start();
503     ASSERT_TRUE(started);
504     {
505       ScopedObjectAccess soa(self);
506       cb_.SetInterestingObject(
507           soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections).Ptr());
508       Monitor::Wait(
509           self,
510           // Just a random class
511           soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections).Ptr(),
512           /*ms*/0,
513           /*ns*/0,
514           /*interruptShouldThrow*/false,
515           /*why*/kWaiting);
516     }
517   }
518   ASSERT_TRUE(cb_.saw_wait_start_);
519   ASSERT_FALSE(cb_.saw_wait_finished_);
520 }
521 
522 }  // namespace art
523