staticvoid DumpCmdLine(std::ostream& os) { #ifdefined(__linux__) // Show the original command line, and the current command line too if it's changed. // On Android, /proc/self/cmdline will have been rewritten to something like "system_server". // Note: The string "Cmd line:" is chosen to match the format used by debuggerd.
std::string current_cmd_line; if (android::base::ReadFileToString("/proc/self/cmdline", ¤t_cmd_line)) {
current_cmd_line.resize(current_cmd_line.find_last_not_of('\0') + 1); // trim trailing '\0's
std::replace(current_cmd_line.begin(), current_cmd_line.end(), '\0', ' ');
// Create a raw pthread; its start routine will attach to the runtime.
CHECK_PTHREAD_CALL(pthread_create, (&pthread_, nullptr, &Run, this), "signal catcher thread");
SignalCatcher::~SignalCatcher() { // Since we know the thread is just sitting around waiting for signals // to arrive, send it one.
SetHaltFlag(true);
CHECK_PTHREAD_CALL(pthread_kill,
(pthread_, SIGQUIT),
android::base::StringPrintf("signal catcher shutdown: %lu", pthread_));
CHECK_PTHREAD_CALL(pthread_join,
(pthread_, nullptr),
android::base::StringPrintf("signal catcher shutdown: %lu", pthread_));
}
// Note: The strings "Build fingerprint:" and "ABI:" are chosen to match the format used by // debuggerd. This allows, for example, the stack tool to work.
std::string fingerprint = runtime->GetFingerprint();
os << "Build fingerprint: '" << (fingerprint.empty() ? "unknown" : fingerprint) << "'\n";
os << "ABI: '" << GetInstructionSetString(runtime->GetInstructionSet()) << "'\n";
os << "Debug Store: " << DebugStoreGetString() << "\n";
if (ShouldEnableProfileCode()) {
std::string str = TraceProfiler::GetLongRunningMethodsString(); if (!str.empty()) {
os << "LongRunningMethods: " << str << "\n";
}
}
runtime->DumpForSigQuit(os);
if ((false)) {
std::string maps; if (android::base::ReadFileToString("/proc/self/maps", &maps)) {
os << "/proc/self/maps:\n" << maps;
}
}
os << "----- end " << getpid() << " -----\n";
Output(os.str());
sigquit_nanotime_ = std::nullopt;
}
void SignalCatcher::HandleMultiplexedSigUsr1(siginfo_t* info) { if (info->si_code != SI_QUEUE) { // If this signal is not generated from sigqueue, fallback to forcing a GC trigger.
HandleSigUsr1(); return;
} // Use the signal's tag to call the correct handler.
uint8_t tag = std::bit_cast<uintptr_t>(info->si_value) & 0xFu; switch (tag) { case0:
HandleLongMethodTracing(info); break; default:
LOG(WARNING) << "SIGUSR1 received via sigqueue with unknown tag: " << static_cast<int>(tag); break;
}
}
void SignalCatcher::HandleSigUsr1() {
LOG(INFO) << "SIGUSR1 forcing GC (no HPROF) and profile save";
Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false);
ProfileSaver::ForceProcessProfiles();
}
void SignalCatcher::HandleLongMethodTracing(siginfo_t* info) { if (info == nullptr) { // The signaler didn't attach a duration, treat this case as a no-op. return;
}
// Extract duration from the signal info // si_value.sival_int contains the integer passed with the signal // This value represent the trace duration in ms // It is safe to ignore the tag here as we durations that are divisible by 16
uint64_t duration_ms = static_cast<uint64_t>(info->si_value.sival_int);
LOG(INFO) << "Received SIGUSR1 signal with long method tracing tag, enabling long method tracing"
<< " for duration :" << duration_ms << " millis"; // Start the long method tracing with the specified duration (in nanoseconds)
TraceProfiler::StartTraceLongRunningMethods(duration_ms * 1000000ULL);
}
// Signals for sigwait() must be blocked but not ignored. We // block signals like SIGQUIT for all threads, so the condition // is met. When the signal hits, we wake up, without any signal // handlers being invoked. int signal_number = signals.Wait(info); if (!ShouldHalt()) { // Let the user know we got the signal, just in case the system's too screwed for us to // actually do what they want us to do...
LOG(INFO) << *self << ": reacting to signal " << signal_number;
// If anyone's holding locks (which might prevent us from getting back into state Runnable), say so...
Runtime::Current()->DumpLockHolders(LOG_STREAM(INFO));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.