Home | History | Annotate | Download | only in runtime
      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