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-alloc-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-alloc-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-inl.h"
48
49 namespace art HIDDEN {
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)91 static void* PthreadsCallback([[maybe_unused]] void* arg) {
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 ScopedObjectAccess soa(self);
168 MakeExecutable(WellKnownClasses::java_lang_Thread.Get());
169
170 StackHandleScope<3u> hs(self);
171 Handle<mirror::String> thread_name = hs.NewHandle(
172 mirror::String::AllocFromModifiedUtf8(self, "ThreadLifecycleCallback test thread"));
173 ASSERT_TRUE(thread_name != nullptr);
174
175 Handle<mirror::Object> thread_group =
176 hs.NewHandle(soa.Decode<mirror::Object>(runtime_->GetMainThreadGroup()));
177 Handle<mirror::Object> thread =
178 WellKnownClasses::java_lang_Thread_init->NewObject<'L', 'L', 'I', 'Z'>(
179 hs, self, thread_group, thread_name, kMinThreadPriority, /*daemon=*/ false);
180 ASSERT_FALSE(self->IsExceptionPending());
181 ASSERT_TRUE(thread != nullptr);
182
183 ArtMethod* start_method =
184 thread->GetClass()->FindClassMethod("start", "()V", kRuntimePointerSize);
185 ASSERT_TRUE(start_method != nullptr);
186
187 start_method->InvokeVirtual<'V'>(self, thread.Get());
188 ASSERT_FALSE(self->IsExceptionPending());
189
190 ArtMethod* join_method = thread->GetClass()->FindClassMethod("join", "()V", kRuntimePointerSize);
191 ASSERT_TRUE(join_method != nullptr);
192
193 join_method->InvokeFinal<'V'>(self, thread.Get());
194 ASSERT_FALSE(self->IsExceptionPending());
195
196 EXPECT_EQ(cb_.state, CallbackState::kDied);
197 }
198
TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest,ThreadLifecycleCallbackAttach)199 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) {
200 std::string error_msg;
201 MemMap stack = MemMap::MapAnonymous("ThreadLifecycleCallback Thread",
202 128 * gPageSize, // Just some small stack.
203 PROT_READ | PROT_WRITE,
204 /*low_4gb=*/ false,
205 &error_msg);
206 ASSERT_TRUE(stack.IsValid()) << error_msg;
207
208 const char* reason = "ThreadLifecycleCallback test thread";
209 pthread_attr_t attr;
210 CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason);
211 CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack.Begin(), stack.Size()), reason);
212 pthread_t pthread;
213 CHECK_PTHREAD_CALL(pthread_create,
214 (&pthread,
215 &attr,
216 &ThreadLifecycleCallbackRuntimeCallbacksTest::PthreadsCallback,
217 this),
218 reason);
219 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason);
220
221 CHECK_PTHREAD_CALL(pthread_join, (pthread, nullptr), "ThreadLifecycleCallback test shutdown");
222
223 // Detach is not a ThreadDeath event, so we expect to be in state Started.
224 EXPECT_TRUE(cb_.state == CallbackState::kStarted) << static_cast<int>(cb_.state);
225 }
226
227 class ClassLoadCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
228 protected:
AddListener()229 void AddListener() override REQUIRES(Locks::mutator_lock_) {
230 Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&cb_);
231 }
RemoveListener()232 void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
233 Runtime::Current()->GetRuntimeCallbacks()->RemoveClassLoadCallback(&cb_);
234 }
235
Expect(std::initializer_list<const char * > list)236 bool Expect(std::initializer_list<const char*> list) {
237 if (cb_.data.size() != list.size()) {
238 PrintError(list);
239 return false;
240 }
241
242 if (!std::equal(cb_.data.begin(), cb_.data.end(), list.begin())) {
243 PrintError(list);
244 return false;
245 }
246
247 return true;
248 }
249
PrintError(std::initializer_list<const char * > list)250 void PrintError(std::initializer_list<const char*> list) {
251 LOG(ERROR) << "Expected:";
252 for (const char* expected : list) {
253 LOG(ERROR) << " " << expected;
254 }
255 LOG(ERROR) << "Found:";
256 for (const auto& s : cb_.data) {
257 LOG(ERROR) << " " << s;
258 }
259 }
260
261 struct Callback : public ClassLoadCallback {
ClassPreDefineart::ClassLoadCallbackRuntimeCallbacksTest::Callback262 void ClassPreDefine(const char* descriptor,
263 [[maybe_unused]] Handle<mirror::Class> klass,
264 [[maybe_unused]] Handle<mirror::ClassLoader> class_loader,
265 const DexFile& initial_dex_file,
266 [[maybe_unused]] const dex::ClassDef& initial_class_def,
267 [[maybe_unused]] /*out*/ DexFile const** final_dex_file,
268 [[maybe_unused]] /*out*/ dex::ClassDef const** final_class_def) override
269 REQUIRES_SHARED(Locks::mutator_lock_) {
270 const std::string& location = initial_dex_file.GetLocation();
271 std::string event =
272 std::string("PreDefine:") + descriptor + " <" +
273 location.substr(location.rfind('/') + 1, location.size()) + ">";
274 data.push_back(event);
275 }
276
ClassLoadart::ClassLoadCallbackRuntimeCallbacksTest::Callback277 void ClassLoad(Handle<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
278 std::string tmp;
279 std::string event = std::string("Load:") + klass->GetDescriptor(&tmp);
280 data.push_back(event);
281 }
282
ClassPrepareart::ClassLoadCallbackRuntimeCallbacksTest::Callback283 void ClassPrepare(Handle<mirror::Class> temp_klass,
284 Handle<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
285 std::string tmp, tmp2;
286 std::string event = std::string("Prepare:") + klass->GetDescriptor(&tmp)
287 + "[" + temp_klass->GetDescriptor(&tmp2) + "]";
288 data.push_back(event);
289 }
290
291 std::vector<std::string> data;
292 };
293
294 Callback cb_;
295 };
296
TEST_F(ClassLoadCallbackRuntimeCallbacksTest,ClassLoadCallback)297 TEST_F(ClassLoadCallbackRuntimeCallbacksTest, ClassLoadCallback) {
298 ScopedObjectAccess soa(Thread::Current());
299 jobject jclass_loader = LoadDex("XandY");
300 cb_.data.clear(); // Clear class loading records from `LoadDex()`, if any.
301 VariableSizedHandleScope hs(soa.Self());
302 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
303 soa.Decode<mirror::ClassLoader>(jclass_loader)));
304
305 const char* descriptor_y = "LY;";
306 Handle<mirror::Class> h_Y(
307 hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader)));
308 ASSERT_TRUE(h_Y != nullptr);
309
310 bool expect1 = Expect({ "PreDefine:LY; <art-gtest-jars-XandY.jar>",
311 "PreDefine:LX; <art-gtest-jars-XandY.jar>",
312 "Load:LX;",
313 "Prepare:LX;[LX;]",
314 "Load:LY;",
315 "Prepare:LY;[LY;]" });
316 EXPECT_TRUE(expect1);
317
318 cb_.data.clear();
319
320 ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true));
321
322 bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-jars-XandY.jar>",
323 "Load:LY$Z;",
324 "Prepare:LY$Z;[LY$Z;]" });
325 EXPECT_TRUE(expect2);
326 }
327
328 class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
329 protected:
AddListener()330 void AddListener() override REQUIRES(Locks::mutator_lock_) {
331 Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&cb_);
332 }
RemoveListener()333 void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
334 Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&cb_);
335 }
336
337 struct Callback : public RuntimeSigQuitCallback {
SigQuitart::RuntimeSigQuitCallbackRuntimeCallbacksTest::Callback338 void SigQuit() override {
339 ++sigquit_count;
340 }
341
342 size_t sigquit_count = 0;
343 };
344
345 Callback cb_;
346 };
347
TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest,SigQuit)348 TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) {
349 // The runtime needs to be started for the signal handler.
350 Thread* self = Thread::Current();
351
352 self->TransitionFromSuspendedToRunnable();
353 bool started = runtime_->Start();
354 ASSERT_TRUE(started);
355
356 EXPECT_EQ(0u, cb_.sigquit_count);
357
358 kill(getpid(), SIGQUIT);
359
360 // Try a few times.
361 for (size_t i = 0; i != 30; ++i) {
362 if (cb_.sigquit_count == 0) {
363 sleep(1);
364 } else {
365 break;
366 }
367 }
368 EXPECT_EQ(1u, cb_.sigquit_count);
369 }
370
371 class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest {
372 protected:
AddListener()373 void AddListener() override REQUIRES(Locks::mutator_lock_) {
374 Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_);
375 }
RemoveListener()376 void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
377 Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_);
378 }
379
TearDown()380 void TearDown() override {
381 // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone.
382 CommonRuntimeTest::TearDown();
383 }
384
385 struct Callback : public RuntimePhaseCallback {
NextRuntimePhaseart::RuntimePhaseCallbackRuntimeCallbacksTest::Callback386 void NextRuntimePhase(RuntimePhaseCallback::RuntimePhase p) override {
387 if (p == RuntimePhaseCallback::RuntimePhase::kInitialAgents) {
388 if (start_seen > 0 || init_seen > 0 || death_seen > 0) {
389 LOG(FATAL) << "Unexpected order";
390 }
391 ++initial_agents_seen;
392 } else if (p == RuntimePhaseCallback::RuntimePhase::kStart) {
393 if (init_seen > 0 || death_seen > 0) {
394 LOG(FATAL) << "Init seen before start.";
395 }
396 ++start_seen;
397 } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) {
398 ++init_seen;
399 } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) {
400 ++death_seen;
401 } else {
402 LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p);
403 }
404 }
405
406 size_t initial_agents_seen = 0;
407 size_t start_seen = 0;
408 size_t init_seen = 0;
409 size_t death_seen = 0;
410 };
411
412 Callback cb_;
413 };
414
TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest,Phases)415 TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest, Phases) {
416 ASSERT_EQ(0u, cb_.initial_agents_seen);
417 ASSERT_EQ(0u, cb_.start_seen);
418 ASSERT_EQ(0u, cb_.init_seen);
419 ASSERT_EQ(0u, cb_.death_seen);
420
421 // Start the runtime.
422 {
423 Thread* self = Thread::Current();
424 self->TransitionFromSuspendedToRunnable();
425 bool started = runtime_->Start();
426 ASSERT_TRUE(started);
427 }
428
429 ASSERT_EQ(0u, cb_.initial_agents_seen);
430 ASSERT_EQ(1u, cb_.start_seen);
431 ASSERT_EQ(1u, cb_.init_seen);
432 ASSERT_EQ(0u, cb_.death_seen);
433
434 // Delete the runtime.
435 runtime_.reset();
436
437 ASSERT_EQ(0u, cb_.initial_agents_seen);
438 ASSERT_EQ(1u, cb_.start_seen);
439 ASSERT_EQ(1u, cb_.init_seen);
440 ASSERT_EQ(1u, cb_.death_seen);
441 }
442
443 class MonitorWaitCallbacksTest : public RuntimeCallbacksTest {
444 protected:
AddListener()445 void AddListener() override REQUIRES(Locks::mutator_lock_) {
446 Runtime::Current()->GetRuntimeCallbacks()->AddMonitorCallback(&cb_);
447 }
RemoveListener()448 void RemoveListener() override REQUIRES(Locks::mutator_lock_) {
449 Runtime::Current()->GetRuntimeCallbacks()->RemoveMonitorCallback(&cb_);
450 }
451
452 struct Callback : public MonitorCallback {
IsInterestingObjectart::MonitorWaitCallbacksTest::Callback453 bool IsInterestingObject(ObjPtr<mirror::Object> obj)
454 REQUIRES_SHARED(art::Locks::mutator_lock_) {
455 if (!obj->IsClass()) {
456 return false;
457 }
458 std::lock_guard<std::mutex> lock(ref_guard_);
459 ObjPtr<mirror::Class> k = obj->AsClass();
460 ClassReference test = { &k->GetDexFile(), k->GetDexClassDefIndex() };
461 return ref_ == test;
462 }
463
SetInterestingObjectart::MonitorWaitCallbacksTest::Callback464 void SetInterestingObject(ObjPtr<mirror::Object> obj)
465 REQUIRES_SHARED(art::Locks::mutator_lock_) {
466 std::lock_guard<std::mutex> lock(ref_guard_);
467 ObjPtr<mirror::Class> k = obj->AsClass();
468 ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() };
469 }
470
MonitorContendedLockingart::MonitorWaitCallbacksTest::Callback471 void MonitorContendedLocking([[maybe_unused]] Monitor* mon) override
472 REQUIRES_SHARED(Locks::mutator_lock_) {}
473
MonitorContendedLockedart::MonitorWaitCallbacksTest::Callback474 void MonitorContendedLocked([[maybe_unused]] Monitor* mon) override
475 REQUIRES_SHARED(Locks::mutator_lock_) {}
476
ObjectWaitStartart::MonitorWaitCallbacksTest::Callback477 void ObjectWaitStart(Handle<mirror::Object> obj, [[maybe_unused]] int64_t millis) override
478 REQUIRES_SHARED(Locks::mutator_lock_) {
479 if (IsInterestingObject(obj.Get())) {
480 saw_wait_start_ = true;
481 }
482 }
483
MonitorWaitFinishedart::MonitorWaitCallbacksTest::Callback484 void MonitorWaitFinished(Monitor* m, [[maybe_unused]] bool timed_out) override
485 REQUIRES_SHARED(Locks::mutator_lock_) {
486 if (IsInterestingObject(m->GetObject())) {
487 saw_wait_finished_ = true;
488 }
489 }
490
491 std::mutex ref_guard_;
492 ClassReference ref_ = {nullptr, 0};
493 bool saw_wait_start_ = false;
494 bool saw_wait_finished_ = false;
495 };
496
497 Callback cb_;
498 };
499
500 // TODO It would be good to have more tests for this but due to the multi-threaded nature of the
501 // callbacks this is difficult. For now the run-tests 1931 & 1932 should be sufficient.
TEST_F(MonitorWaitCallbacksTest,WaitUnlocked)502 TEST_F(MonitorWaitCallbacksTest, WaitUnlocked) {
503 ASSERT_FALSE(cb_.saw_wait_finished_);
504 ASSERT_FALSE(cb_.saw_wait_start_);
505 {
506 Thread* self = Thread::Current();
507 self->TransitionFromSuspendedToRunnable();
508 bool started = runtime_->Start();
509 ASSERT_TRUE(started);
510 {
511 ScopedObjectAccess soa(self);
512 cb_.SetInterestingObject(WellKnownClasses::java_util_Collections.Get());
513 Monitor::Wait(
514 self,
515 // Just a random class
516 WellKnownClasses::java_util_Collections.Get(),
517 /*ms=*/0,
518 /*ns=*/0,
519 /*interruptShouldThrow=*/false,
520 /*why=*/ThreadState::kWaiting);
521 }
522 }
523 ASSERT_TRUE(cb_.saw_wait_start_);
524 ASSERT_FALSE(cb_.saw_wait_finished_);
525 }
526
527 } // namespace art
528