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 "jni.h" 20 #include <signal.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 #include <initializer_list> 25 #include <memory> 26 #include <string> 27 28 #include "art_method-inl.h" 29 #include "base/mutex.h" 30 #include "class_linker.h" 31 #include "common_runtime_test.h" 32 #include "handle.h" 33 #include "handle_scope-inl.h" 34 #include "mem_map.h" 35 #include "mirror/class-inl.h" 36 #include "mirror/class_loader.h" 37 #include "nativehelper/ScopedLocalRef.h" 38 #include "obj_ptr.h" 39 #include "runtime.h" 40 #include "scoped_thread_state_change-inl.h" 41 #include "thread-inl.h" 42 #include "thread_list.h" 43 #include "well_known_classes.h" 44 45 namespace art { 46 47 class RuntimeCallbacksTest : public CommonRuntimeTest { 48 protected: 49 void SetUp() OVERRIDE { 50 CommonRuntimeTest::SetUp(); 51 52 Thread* self = Thread::Current(); 53 ScopedObjectAccess soa(self); 54 ScopedThreadSuspension sts(self, kWaitingForDebuggerToAttach); 55 ScopedSuspendAll ssa("RuntimeCallbacksTest SetUp"); 56 AddListener(); 57 } 58 59 void TearDown() OVERRIDE { 60 { 61 Thread* self = Thread::Current(); 62 ScopedObjectAccess soa(self); 63 ScopedThreadSuspension sts(self, kWaitingForDebuggerToAttach); 64 ScopedSuspendAll ssa("RuntimeCallbacksTest TearDown"); 65 RemoveListener(); 66 } 67 68 CommonRuntimeTest::TearDown(); 69 } 70 71 virtual void AddListener() REQUIRES(Locks::mutator_lock_) = 0; 72 virtual void RemoveListener() REQUIRES(Locks::mutator_lock_) = 0; 73 74 void MakeExecutable(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) { 75 CHECK(klass != nullptr); 76 PointerSize pointer_size = class_linker_->GetImagePointerSize(); 77 for (auto& m : klass->GetMethods(pointer_size)) { 78 if (!m.IsAbstract()) { 79 class_linker_->SetEntryPointsToInterpreter(&m); 80 } 81 } 82 } 83 }; 84 85 class ThreadLifecycleCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest { 86 public: 87 static void* PthreadsCallback(void* arg ATTRIBUTE_UNUSED) { 88 // Attach. 89 Runtime* runtime = Runtime::Current(); 90 CHECK(runtime->AttachCurrentThread("ThreadLifecycle test thread", true, nullptr, false)); 91 92 // Detach. 93 runtime->DetachCurrentThread(); 94 95 // Die... 96 return nullptr; 97 } 98 99 protected: 100 void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) { 101 Runtime::Current()->GetRuntimeCallbacks()->AddThreadLifecycleCallback(&cb_); 102 } 103 void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) { 104 Runtime::Current()->GetRuntimeCallbacks()->RemoveThreadLifecycleCallback(&cb_); 105 } 106 107 enum CallbackState { 108 kBase, 109 kStarted, 110 kDied, 111 kWrongStart, 112 kWrongDeath, 113 }; 114 115 struct Callback : public ThreadLifecycleCallback { 116 void ThreadStart(Thread* self) OVERRIDE { 117 if (state == CallbackState::kBase) { 118 state = CallbackState::kStarted; 119 stored_self = self; 120 } else { 121 state = CallbackState::kWrongStart; 122 } 123 } 124 125 void ThreadDeath(Thread* self) OVERRIDE { 126 if (state == CallbackState::kStarted && self == stored_self) { 127 state = CallbackState::kDied; 128 } else { 129 state = CallbackState::kWrongDeath; 130 } 131 } 132 133 Thread* stored_self; 134 CallbackState state = CallbackState::kBase; 135 }; 136 137 Callback cb_; 138 }; 139 140 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackJava) { 141 Thread* self = Thread::Current(); 142 143 self->TransitionFromSuspendedToRunnable(); 144 bool started = runtime_->Start(); 145 ASSERT_TRUE(started); 146 147 cb_.state = CallbackState::kBase; // Ignore main thread attach. 148 149 { 150 ScopedObjectAccess soa(self); 151 MakeExecutable(soa.Decode<mirror::Class>(WellKnownClasses::java_lang_Thread)); 152 } 153 154 JNIEnv* env = self->GetJniEnv(); 155 156 ScopedLocalRef<jobject> thread_name(env, 157 env->NewStringUTF("ThreadLifecycleCallback test thread")); 158 ASSERT_TRUE(thread_name.get() != nullptr); 159 160 ScopedLocalRef<jobject> thread(env, env->AllocObject(WellKnownClasses::java_lang_Thread)); 161 ASSERT_TRUE(thread.get() != nullptr); 162 163 env->CallNonvirtualVoidMethod(thread.get(), 164 WellKnownClasses::java_lang_Thread, 165 WellKnownClasses::java_lang_Thread_init, 166 runtime_->GetMainThreadGroup(), 167 thread_name.get(), 168 kMinThreadPriority, 169 JNI_FALSE); 170 ASSERT_FALSE(env->ExceptionCheck()); 171 172 jmethodID start_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "start", "()V"); 173 ASSERT_TRUE(start_id != nullptr); 174 175 env->CallVoidMethod(thread.get(), start_id); 176 ASSERT_FALSE(env->ExceptionCheck()); 177 178 jmethodID join_id = env->GetMethodID(WellKnownClasses::java_lang_Thread, "join", "()V"); 179 ASSERT_TRUE(join_id != nullptr); 180 181 env->CallVoidMethod(thread.get(), join_id); 182 ASSERT_FALSE(env->ExceptionCheck()); 183 184 EXPECT_TRUE(cb_.state == CallbackState::kDied) << static_cast<int>(cb_.state); 185 } 186 187 TEST_F(ThreadLifecycleCallbackRuntimeCallbacksTest, ThreadLifecycleCallbackAttach) { 188 std::string error_msg; 189 std::unique_ptr<MemMap> stack(MemMap::MapAnonymous("ThreadLifecycleCallback Thread", 190 nullptr, 191 128 * kPageSize, // Just some small stack. 192 PROT_READ | PROT_WRITE, 193 false, 194 false, 195 &error_msg)); 196 ASSERT_FALSE(stack == nullptr) << error_msg; 197 198 const char* reason = "ThreadLifecycleCallback test thread"; 199 pthread_attr_t attr; 200 CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), reason); 201 CHECK_PTHREAD_CALL(pthread_attr_setstack, (&attr, stack->Begin(), stack->Size()), reason); 202 pthread_t pthread; 203 CHECK_PTHREAD_CALL(pthread_create, 204 (&pthread, 205 &attr, 206 &ThreadLifecycleCallbackRuntimeCallbacksTest::PthreadsCallback, 207 this), 208 reason); 209 CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), reason); 210 211 CHECK_PTHREAD_CALL(pthread_join, (pthread, nullptr), "ThreadLifecycleCallback test shutdown"); 212 213 // Detach is not a ThreadDeath event, so we expect to be in state Started. 214 EXPECT_TRUE(cb_.state == CallbackState::kStarted) << static_cast<int>(cb_.state); 215 } 216 217 class ClassLoadCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest { 218 protected: 219 void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) { 220 Runtime::Current()->GetRuntimeCallbacks()->AddClassLoadCallback(&cb_); 221 } 222 void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) { 223 Runtime::Current()->GetRuntimeCallbacks()->RemoveClassLoadCallback(&cb_); 224 } 225 226 bool Expect(std::initializer_list<const char*> list) { 227 if (cb_.data.size() != list.size()) { 228 PrintError(list); 229 return false; 230 } 231 232 if (!std::equal(cb_.data.begin(), cb_.data.end(), list.begin())) { 233 PrintError(list); 234 return false; 235 } 236 237 return true; 238 } 239 240 void PrintError(std::initializer_list<const char*> list) { 241 LOG(ERROR) << "Expected:"; 242 for (const char* expected : list) { 243 LOG(ERROR) << " " << expected; 244 } 245 LOG(ERROR) << "Found:"; 246 for (const auto& s : cb_.data) { 247 LOG(ERROR) << " " << s; 248 } 249 } 250 251 struct Callback : public ClassLoadCallback { 252 virtual void ClassPreDefine(const char* descriptor, 253 Handle<mirror::Class> klass ATTRIBUTE_UNUSED, 254 Handle<mirror::ClassLoader> class_loader ATTRIBUTE_UNUSED, 255 const DexFile& initial_dex_file, 256 const DexFile::ClassDef& initial_class_def ATTRIBUTE_UNUSED, 257 /*out*/DexFile const** final_dex_file ATTRIBUTE_UNUSED, 258 /*out*/DexFile::ClassDef const** final_class_def ATTRIBUTE_UNUSED) 259 OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 260 std::string location(initial_dex_file.GetLocation()); 261 std::string event = 262 std::string("PreDefine:") + descriptor + " <" + 263 location.substr(location.rfind("/") + 1, location.size()) + ">"; 264 data.push_back(event); 265 } 266 267 void ClassLoad(Handle<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 268 std::string tmp; 269 std::string event = std::string("Load:") + klass->GetDescriptor(&tmp); 270 data.push_back(event); 271 } 272 273 void ClassPrepare(Handle<mirror::Class> temp_klass, 274 Handle<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 275 std::string tmp, tmp2; 276 std::string event = std::string("Prepare:") + klass->GetDescriptor(&tmp) 277 + "[" + temp_klass->GetDescriptor(&tmp2) + "]"; 278 data.push_back(event); 279 } 280 281 std::vector<std::string> data; 282 }; 283 284 Callback cb_; 285 }; 286 287 TEST_F(ClassLoadCallbackRuntimeCallbacksTest, ClassLoadCallback) { 288 ScopedObjectAccess soa(Thread::Current()); 289 jobject jclass_loader = LoadDex("XandY"); 290 VariableSizedHandleScope hs(soa.Self()); 291 Handle<mirror::ClassLoader> class_loader(hs.NewHandle( 292 soa.Decode<mirror::ClassLoader>(jclass_loader))); 293 294 const char* descriptor_y = "LY;"; 295 Handle<mirror::Class> h_Y( 296 hs.NewHandle(class_linker_->FindClass(soa.Self(), descriptor_y, class_loader))); 297 ASSERT_TRUE(h_Y != nullptr); 298 299 bool expect1 = Expect({ "PreDefine:LY; <art-gtest-XandY.jar>", 300 "PreDefine:LX; <art-gtest-XandY.jar>", 301 "Load:LX;", 302 "Prepare:LX;[LX;]", 303 "Load:LY;", 304 "Prepare:LY;[LY;]" }); 305 EXPECT_TRUE(expect1); 306 307 cb_.data.clear(); 308 309 ASSERT_TRUE(class_linker_->EnsureInitialized(Thread::Current(), h_Y, true, true)); 310 311 bool expect2 = Expect({ "PreDefine:LY$Z; <art-gtest-XandY.jar>", 312 "Load:LY$Z;", 313 "Prepare:LY$Z;[LY$Z;]" }); 314 EXPECT_TRUE(expect2); 315 } 316 317 class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest { 318 protected: 319 void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) { 320 Runtime::Current()->GetRuntimeCallbacks()->AddRuntimeSigQuitCallback(&cb_); 321 } 322 void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) { 323 Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimeSigQuitCallback(&cb_); 324 } 325 326 struct Callback : public RuntimeSigQuitCallback { 327 void SigQuit() OVERRIDE { 328 ++sigquit_count; 329 } 330 331 size_t sigquit_count = 0; 332 }; 333 334 Callback cb_; 335 }; 336 337 TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) { 338 // SigQuit induces a dump. ASAN isn't happy with libunwind reading memory. 339 TEST_DISABLED_FOR_MEMORY_TOOL_ASAN(); 340 341 // The runtime needs to be started for the signal handler. 342 Thread* self = Thread::Current(); 343 344 self->TransitionFromSuspendedToRunnable(); 345 bool started = runtime_->Start(); 346 ASSERT_TRUE(started); 347 348 EXPECT_EQ(0u, cb_.sigquit_count); 349 350 kill(getpid(), SIGQUIT); 351 352 // Try a few times. 353 for (size_t i = 0; i != 30; ++i) { 354 if (cb_.sigquit_count == 0) { 355 sleep(1); 356 } else { 357 break; 358 } 359 } 360 EXPECT_EQ(1u, cb_.sigquit_count); 361 } 362 363 class RuntimePhaseCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest { 364 protected: 365 void AddListener() OVERRIDE REQUIRES(Locks::mutator_lock_) { 366 Runtime::Current()->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&cb_); 367 } 368 void RemoveListener() OVERRIDE REQUIRES(Locks::mutator_lock_) { 369 Runtime::Current()->GetRuntimeCallbacks()->RemoveRuntimePhaseCallback(&cb_); 370 } 371 372 void TearDown() OVERRIDE { 373 // Bypass RuntimeCallbacksTest::TearDown, as the runtime is already gone. 374 CommonRuntimeTest::TearDown(); 375 } 376 377 struct Callback : public RuntimePhaseCallback { 378 void NextRuntimePhase(RuntimePhaseCallback::RuntimePhase p) OVERRIDE { 379 if (p == RuntimePhaseCallback::RuntimePhase::kInitialAgents) { 380 if (start_seen > 0 || init_seen > 0 || death_seen > 0) { 381 LOG(FATAL) << "Unexpected order"; 382 } 383 ++initial_agents_seen; 384 } else if (p == RuntimePhaseCallback::RuntimePhase::kStart) { 385 if (init_seen > 0 || death_seen > 0) { 386 LOG(FATAL) << "Init seen before start."; 387 } 388 ++start_seen; 389 } else if (p == RuntimePhaseCallback::RuntimePhase::kInit) { 390 ++init_seen; 391 } else if (p == RuntimePhaseCallback::RuntimePhase::kDeath) { 392 ++death_seen; 393 } else { 394 LOG(FATAL) << "Unknown phase " << static_cast<uint32_t>(p); 395 } 396 } 397 398 size_t initial_agents_seen = 0; 399 size_t start_seen = 0; 400 size_t init_seen = 0; 401 size_t death_seen = 0; 402 }; 403 404 Callback cb_; 405 }; 406 407 TEST_F(RuntimePhaseCallbackRuntimeCallbacksTest, Phases) { 408 ASSERT_EQ(0u, cb_.initial_agents_seen); 409 ASSERT_EQ(0u, cb_.start_seen); 410 ASSERT_EQ(0u, cb_.init_seen); 411 ASSERT_EQ(0u, cb_.death_seen); 412 413 // Start the runtime. 414 { 415 Thread* self = Thread::Current(); 416 self->TransitionFromSuspendedToRunnable(); 417 bool started = runtime_->Start(); 418 ASSERT_TRUE(started); 419 } 420 421 ASSERT_EQ(0u, cb_.initial_agents_seen); 422 ASSERT_EQ(1u, cb_.start_seen); 423 ASSERT_EQ(1u, cb_.init_seen); 424 ASSERT_EQ(0u, cb_.death_seen); 425 426 // Delete the runtime. 427 runtime_.reset(); 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(1u, cb_.death_seen); 433 } 434 435 } // namespace art 436