Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2008 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 "signal_catcher.h"
     18 
     19 #include <csignal>
     20 #include <cstdlib>
     21 #include <fcntl.h>
     22 #include <pthread.h>
     23 #include <sys/stat.h>
     24 #include <sys/time.h>
     25 #include <sys/types.h>
     26 #include <unistd.h>
     27 
     28 #include <sstream>
     29 
     30 #include <android-base/stringprintf.h>
     31 
     32 #include "arch/instruction_set.h"
     33 #include "base/logging.h"  // For GetCmdLine.
     34 #include "base/os.h"
     35 #include "base/time_utils.h"
     36 #include "base/utils.h"
     37 #include "class_linker.h"
     38 #include "gc/heap.h"
     39 #include "jit/profile_saver.h"
     40 #include "palette/palette.h"
     41 #include "runtime.h"
     42 #include "scoped_thread_state_change-inl.h"
     43 #include "signal_set.h"
     44 #include "thread.h"
     45 #include "thread_list.h"
     46 
     47 namespace art {
     48 
     49 static void DumpCmdLine(std::ostream& os) {
     50 #if defined(__linux__)
     51   // Show the original command line, and the current command line too if it's changed.
     52   // On Android, /proc/self/cmdline will have been rewritten to something like "system_server".
     53   // Note: The string "Cmd line:" is chosen to match the format used by debuggerd.
     54   std::string current_cmd_line;
     55   if (ReadFileToString("/proc/self/cmdline", &current_cmd_line)) {
     56     current_cmd_line.resize(current_cmd_line.find_last_not_of('\0') + 1);  // trim trailing '\0's
     57     std::replace(current_cmd_line.begin(), current_cmd_line.end(), '\0', ' ');
     58 
     59     os << "Cmd line: " << current_cmd_line << "\n";
     60     const char* stashed_cmd_line = GetCmdLine();
     61     if (stashed_cmd_line != nullptr && current_cmd_line != stashed_cmd_line
     62             && strcmp(stashed_cmd_line, "<unset>") != 0) {
     63       os << "Original command line: " << stashed_cmd_line << "\n";
     64     }
     65   }
     66 #else
     67   os << "Cmd line: " << GetCmdLine() << "\n";
     68 #endif
     69 }
     70 
     71 SignalCatcher::SignalCatcher()
     72     : lock_("SignalCatcher lock"),
     73       cond_("SignalCatcher::cond_", lock_),
     74       thread_(nullptr) {
     75   SetHaltFlag(false);
     76 
     77   // Create a raw pthread; its start routine will attach to the runtime.
     78   CHECK_PTHREAD_CALL(pthread_create, (&pthread_, nullptr, &Run, this), "signal catcher thread");
     79 
     80   Thread* self = Thread::Current();
     81   MutexLock mu(self, lock_);
     82   while (thread_ == nullptr) {
     83     cond_.Wait(self);
     84   }
     85 }
     86 
     87 SignalCatcher::~SignalCatcher() {
     88   // Since we know the thread is just sitting around waiting for signals
     89   // to arrive, send it one.
     90   SetHaltFlag(true);
     91   CHECK_PTHREAD_CALL(pthread_kill, (pthread_, SIGQUIT), "signal catcher shutdown");
     92   CHECK_PTHREAD_CALL(pthread_join, (pthread_, nullptr), "signal catcher shutdown");
     93 }
     94 
     95 void SignalCatcher::SetHaltFlag(bool new_value) {
     96   MutexLock mu(Thread::Current(), lock_);
     97   halt_ = new_value;
     98 }
     99 
    100 bool SignalCatcher::ShouldHalt() {
    101   MutexLock mu(Thread::Current(), lock_);
    102   return halt_;
    103 }
    104 
    105 void SignalCatcher::Output(const std::string& s) {
    106   ScopedThreadStateChange tsc(Thread::Current(), kWaitingForSignalCatcherOutput);
    107   PaletteStatus status = PaletteWriteCrashThreadStacks(s.data(), s.size());
    108   if (status == PaletteStatus::kOkay) {
    109     LOG(INFO) << "Wrote stack traces to tombstoned";
    110   } else {
    111     CHECK(status == PaletteStatus::kFailedCheckLog);
    112     LOG(ERROR) << "Failed to write stack traces to tombstoned";
    113   }
    114 }
    115 
    116 void SignalCatcher::HandleSigQuit() {
    117   Runtime* runtime = Runtime::Current();
    118   std::ostringstream os;
    119   os << "\n"
    120       << "----- pid " << getpid() << " at " << GetIsoDate() << " -----\n";
    121 
    122   DumpCmdLine(os);
    123 
    124   // Note: The strings "Build fingerprint:" and "ABI:" are chosen to match the format used by
    125   // debuggerd. This allows, for example, the stack tool to work.
    126   std::string fingerprint = runtime->GetFingerprint();
    127   os << "Build fingerprint: '" << (fingerprint.empty() ? "unknown" : fingerprint) << "'\n";
    128   os << "ABI: '" << GetInstructionSetString(runtime->GetInstructionSet()) << "'\n";
    129 
    130   os << "Build type: " << (kIsDebugBuild ? "debug" : "optimized") << "\n";
    131 
    132   runtime->DumpForSigQuit(os);
    133 
    134   if ((false)) {
    135     std::string maps;
    136     if (ReadFileToString("/proc/self/maps", &maps)) {
    137       os << "/proc/self/maps:\n" << maps;
    138     }
    139   }
    140   os << "----- end " << getpid() << " -----\n";
    141   Output(os.str());
    142 }
    143 
    144 void SignalCatcher::HandleSigUsr1() {
    145   LOG(INFO) << "SIGUSR1 forcing GC (no HPROF) and profile save";
    146   Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false);
    147   ProfileSaver::ForceProcessProfiles();
    148 }
    149 
    150 int SignalCatcher::WaitForSignal(Thread* self, SignalSet& signals) {
    151   ScopedThreadStateChange tsc(self, kWaitingInMainSignalCatcherLoop);
    152 
    153   // Signals for sigwait() must be blocked but not ignored.  We
    154   // block signals like SIGQUIT for all threads, so the condition
    155   // is met.  When the signal hits, we wake up, without any signal
    156   // handlers being invoked.
    157   int signal_number = signals.Wait();
    158   if (!ShouldHalt()) {
    159     // Let the user know we got the signal, just in case the system's too screwed for us to
    160     // actually do what they want us to do...
    161     LOG(INFO) << *self << ": reacting to signal " << signal_number;
    162 
    163     // If anyone's holding locks (which might prevent us from getting back into state Runnable), say so...
    164     Runtime::Current()->DumpLockHolders(LOG_STREAM(INFO));
    165   }
    166 
    167   return signal_number;
    168 }
    169 
    170 void* SignalCatcher::Run(void* arg) {
    171   SignalCatcher* signal_catcher = reinterpret_cast<SignalCatcher*>(arg);
    172   CHECK(signal_catcher != nullptr);
    173 
    174   Runtime* runtime = Runtime::Current();
    175   CHECK(runtime->AttachCurrentThread("Signal Catcher", true, runtime->GetSystemThreadGroup(),
    176                                      !runtime->IsAotCompiler()));
    177 
    178   Thread* self = Thread::Current();
    179   DCHECK_NE(self->GetState(), kRunnable);
    180   {
    181     MutexLock mu(self, signal_catcher->lock_);
    182     signal_catcher->thread_ = self;
    183     signal_catcher->cond_.Broadcast(self);
    184   }
    185 
    186   // Set up mask with signals we want to handle.
    187   SignalSet signals;
    188   signals.Add(SIGQUIT);
    189   signals.Add(SIGUSR1);
    190 
    191   while (true) {
    192     int signal_number = signal_catcher->WaitForSignal(self, signals);
    193     if (signal_catcher->ShouldHalt()) {
    194       runtime->DetachCurrentThread();
    195       return nullptr;
    196     }
    197 
    198     switch (signal_number) {
    199     case SIGQUIT:
    200       signal_catcher->HandleSigQuit();
    201       break;
    202     case SIGUSR1:
    203       signal_catcher->HandleSigUsr1();
    204       break;
    205     default:
    206       LOG(ERROR) << "Unexpected signal %d" << signal_number;
    207       break;
    208     }
    209   }
    210 }
    211 
    212 }  // namespace art
    213