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, 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 // Make sure the workers are done starting so we don't get callbacks for them.
151 runtime_->WaitForThreadPoolWorkersToStart();
152
153 cb_.state = CallbackState::kBase; // Ignore main thread attach.
154
155 {
156 ScopedObjectAccess soa(self);
157 MakeExecutable(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread));
158 }
159
160 JNIEnv* env = self->GetJniEnv();
161
162 ScopedLocalRef<jobject> thread_name(env,
163 env->NewStringUTF("ThreadLifecycleCallback test thread"));
164 ASSERT_TRUE(thread_name.get() != nullptr);
165
166 ScopedLocalRef<jobject> thread(env, env->AllocObject(WellKnownClasses::java_lang_Thread));
167 ASSERT_TRUE(thread.get() != nullptr);
168
169 env->CallNonvirtualVoidMethod(thread.get(),
170 WellKnownClasses::java_lang_Thread,
171 WellKnownClasses::java_lang_Thread_init,
172 runtime_->GetMainThreadGroup(),
173 thread_name.get(),
174 kMinThreadPriority,
175 JNI_FALSE);
176 ASSERT_FALSE(env->ExceptionCheck());
177
178 jmethodID start_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "start", "()V");
179 ASSERT_TRUE(start_id != nullptr);
180
181 env->CallVoidMethod(thread.get(), start_id);
182 ASSERT_FALSE(env->ExceptionCheck());
183
184 jmethodID join_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "join", "()V");
185 ASSERT_TRUE(join_id != nullptr);
186
187 env->CallVoidMethod(thread.get(), join_id);
188 ASSERT_FALSE(env->ExceptionCheck());
189
190 EXPECT_TRUE(cb_.state == CallbackState::kDied) << static_cast<int>(cb_.state);
191 }
192
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackAttach)193 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
194 std::string error_msg;
195 MemMap stack = MemMap::MapAnonymous("ThreadLifecycleCallback Thread",
196 128 * kPageSize, // Just some small stack.
197 PROT_READ | PROT_WRITE,
198 /*low_4gb=*/ false,
199 &error_msg);
200 ASSERT_TRUE(stack.IsValid()) << 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 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 dex::ClassDef& initial_class_def ATTRIBUTE_UNUSED,
261 /*out*/DexFile const** final_dex_file ATTRIBUTE_UNUSED,
262 /*out*/dex::ClassDef const** final_class_def ATTRIBUTE_UNUSED) override
263 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 // The runtime needs to be started for the signal handler.
343 Thread* self = Thread::Current();
344
345 self->TransitionFromSuspendedToRunnable();
346 bool started = runtime_->Start();
347 ASSERT_TRUE(started);
348
349 EXPECT_EQ(0u, cb_.sigquit_count);
350
351 kill(getpid(), SIGQUIT);
352
353 // Try a few times.
354 for (size_t i = 0; i != 30; ++i) {
355 if (cb_.sigquit_count == 0) {
356 sleep(1);
357 } else {
358 break;
359 }
360 }
361 EXPECT_EQ(1u, cb_.sigquit_count);
362 }
363
364 class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
365 protected:
AddListener()366 void AddListener() override REQUIRES(Locks::mutator_lock_) {
367 Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_);
368 }
RemoveListener()369 void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
370 Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_);
371 }
372
TearDown()373 void TearDown() override {
374 // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone.
375 CommonRuntimeTest::TearDown();
376 }
377
378 struct Callback : public RuntimePhaseCallback {
NextRuntimePhaseart::RuntimePhaseCallbackRuntimeCallbacksTest::Callback379 void NextRuntimePhase(RuntimePhaseCallback::RuntimePhase p) override {
380 if (p == RuntimePhaseCallback::RuntimePhase::kInitialAgents) {
381 if (start_seen > 0 || init_seen > 0 || death_seen > 0) {
382 LOG(FATAL) << "Unexpected order";
383 }
384 ++initial_agents_seen;
385 } else if (p == RuntimePhaseCallback::RuntimePhase::kStart) {
386 if (init_seen > 0 || death_seen > 0) {
387 LOG(FATAL) << "Init seen before start.";
388 }
389 ++start_seen;
390 } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) {
391 ++init_seen;
392 } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) {
393 ++death_seen;
394 } else {
395 LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p);
396 }
397 }
398
399 size_t initial_agents_seen = 0;
400 size_t start_seen = 0;
401 size_t init_seen = 0;
402 size_t death_seen = 0;
403 };
404
405 Callback cb_;
406 };
407
TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest,Phases)408 TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest, Phases) {
409 ASSERT_EQ(0u, cb_.initial_agents_seen);
410 ASSERT_EQ(0u, cb_.start_seen);
411 ASSERT_EQ(0u, cb_.init_seen);
412 ASSERT_EQ(0u, cb_.death_seen);
413
414 // Start the runtime.
415 {
416 Thread* self = Thread::Current();
417 self->TransitionFromSuspendedToRunnable();
418 bool started = runtime_->Start();
419 ASSERT_TRUE(started);
420 }
421
422 ASSERT_EQ(0u, cb_.initial_agents_seen);
423 ASSERT_EQ(1u, cb_.start_seen);
424 ASSERT_EQ(1u, cb_.init_seen);
425 ASSERT_EQ(0u, cb_.death_seen);
426
427 // Delete the runtime.
428 runtime_.reset();
429
430 ASSERT_EQ(0u, cb_.initial_agents_seen);
431 ASSERT_EQ(1u, cb_.start_seen);
432 ASSERT_EQ(1u, cb_.init_seen);
433 ASSERT_EQ(1u, cb_.death_seen);
434 }
435
436 class MonitorWaitCallbacksTest : public RuntimeCallbacksTest {
437 protected:
AddListener()438 void AddListener() override REQUIRES(Locks::mutator_lock_) {
439 Runtime::Current()->GetRuntimeCallbacks()->AddMonitorCallback(&cb_);
440 }
RemoveListener()441 void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
442 Runtime::Current()->GetRuntimeCallbacks()->RemoveMonitorCallback(&cb_);
443 }
444
445 struct Callback : public MonitorCallback {
IsInterestingObjectart::MonitorWaitCallbacksTest::Callback446 bool IsInterestingObject(ObjPtr<mirror::Object> obj)
447 REQUIRES_SHARED(art::Locks::mutator_lock_) {
448 if (!obj->IsClass()) {
449 return false;
450 }
451 std::lock_guard<std::mutex> lock(ref_guard_);
452 ObjPtr<mirror::Class> k = obj->AsClass();
453 ClassReference test = { &k->GetDexFile(), k->GetDexClassDefIndex() };
454 return ref_ == test;
455 }
456
SetInterestingObjectart::MonitorWaitCallbacksTest::Callback457 void SetInterestingObject(ObjPtr<mirror::Object> obj)
458 REQUIRES_SHARED(art::Locks::mutator_lock_) {
459 std::lock_guard<std::mutex> lock(ref_guard_);
460 ObjPtr<mirror::Class> k = obj->AsClass();
461 ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() };
462 }
463
MonitorContendedLockingart::MonitorWaitCallbacksTest::Callback464 void MonitorContendedLocking(Monitor* mon ATTRIBUTE_UNUSED) override
465 REQUIRES_SHARED(Locks::mutator_lock_) { }
466
MonitorContendedLockedart::MonitorWaitCallbacksTest::Callback467 void MonitorContendedLocked(Monitor* mon ATTRIBUTE_UNUSED) override
468 REQUIRES_SHARED(Locks::mutator_lock_) { }
469
ObjectWaitStartart::MonitorWaitCallbacksTest::Callback470 void ObjectWaitStart(Handle<mirror::Object> obj, int64_t millis ATTRIBUTE_UNUSED) override
471 REQUIRES_SHARED(Locks::mutator_lock_) {
472 if (IsInterestingObject(obj.Get())) {
473 saw_wait_start_ = true;
474 }
475 }
476
MonitorWaitFinishedart::MonitorWaitCallbacksTest::Callback477 void MonitorWaitFinished(Monitor* m, bool timed_out ATTRIBUTE_UNUSED) override
478 REQUIRES_SHARED(Locks::mutator_lock_) {
479 if (IsInterestingObject(m->GetObject())) {
480 saw_wait_finished_ = true;
481 }
482 }
483
484 std::mutex ref_guard_;
485 ClassReference ref_ = {nullptr, 0};
486 bool saw_wait_start_ = false;
487 bool saw_wait_finished_ = false;
488 };
489
490 Callback cb_;
491 };
492
493 // TODO It would be good to have more tests for this but due to the multi-threaded nature of the
494 // callbacks this is difficult. For now the run-tests 1931 & 1932 should be sufficient.
TEST_F(MonitorWaitCallbacksTest,WaitUnlocked)495 TEST_F(MonitorWaitCallbacksTest, WaitUnlocked) {
496 ASSERT_FALSE(cb_.saw_wait_finished_);
497 ASSERT_FALSE(cb_.saw_wait_start_);
498 {
499 Thread* self = Thread::Current();
500 self->TransitionFromSuspendedToRunnable();
501 bool started = runtime_->Start();
502 ASSERT_TRUE(started);
503 {
504 ScopedObjectAccess soa(self);
505 cb_.SetInterestingObject(
506 soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections));
507 Monitor::Wait(
508 self,
509 // Just a random class
510 soa.Decode<mirror::Class>(WellKnownClasses::java_util_Collections),
511 /*ms=*/0,
512 /*ns=*/0,
513 /*interruptShouldThrow=*/false,
514 /*why=*/kWaiting);
515 }
516 }
517 ASSERT_TRUE(cb_.saw_wait_start_);
518 ASSERT_FALSE(cb_.saw_wait_finished_);
519 }
520
521 } // namespace art
522