Merge "Allow configuration of the number of tombstones." am: 3e8d923276
am: 216ac36534
Change-Id: I2a7b3950d841b7d458c0a66f402f49780caae6a0
This commit is contained in:
commit
03cec0a7db
1 changed files with 40 additions and 42 deletions
|
|
@ -32,6 +32,7 @@
|
||||||
#include <event2/thread.h>
|
#include <event2/thread.h>
|
||||||
|
|
||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/properties.h>
|
||||||
#include <android-base/stringprintf.h>
|
#include <android-base/stringprintf.h>
|
||||||
#include <android-base/unique_fd.h>
|
#include <android-base/unique_fd.h>
|
||||||
#include <cutils/sockets.h>
|
#include <cutils/sockets.h>
|
||||||
|
|
@ -43,6 +44,7 @@
|
||||||
|
|
||||||
#include "intercept_manager.h"
|
#include "intercept_manager.h"
|
||||||
|
|
||||||
|
using android::base::GetIntProperty;
|
||||||
using android::base::StringPrintf;
|
using android::base::StringPrintf;
|
||||||
using android::base::unique_fd;
|
using android::base::unique_fd;
|
||||||
|
|
||||||
|
|
@ -53,7 +55,19 @@ enum CrashStatus {
|
||||||
kCrashStatusQueued,
|
kCrashStatusQueued,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Crash;
|
// Ownership of Crash is a bit messy.
|
||||||
|
// It's either owned by an active event that must have a timeout, or owned by
|
||||||
|
// queued_requests, in the case that multiple crashes come in at the same time.
|
||||||
|
struct Crash {
|
||||||
|
~Crash() { event_free(crash_event); }
|
||||||
|
|
||||||
|
unique_fd crash_fd;
|
||||||
|
pid_t crash_pid;
|
||||||
|
event* crash_event = nullptr;
|
||||||
|
std::string crash_path;
|
||||||
|
|
||||||
|
DebuggerdDumpType crash_type;
|
||||||
|
};
|
||||||
|
|
||||||
class CrashQueue {
|
class CrashQueue {
|
||||||
public:
|
public:
|
||||||
|
|
@ -77,6 +91,24 @@ class CrashQueue {
|
||||||
find_oldest_artifact();
|
find_oldest_artifact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CrashQueue* for_crash(const Crash* crash) {
|
||||||
|
return (crash->crash_type == kDebuggerdJavaBacktrace) ? for_anrs() : for_tombstones();
|
||||||
|
}
|
||||||
|
|
||||||
|
static CrashQueue* for_tombstones() {
|
||||||
|
static CrashQueue queue("/data/tombstones", "tombstone_" /* file_name_prefix */,
|
||||||
|
GetIntProperty("tombstoned.max_tombstone_count", 10),
|
||||||
|
1 /* max_concurrent_dumps */);
|
||||||
|
return &queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CrashQueue* for_anrs() {
|
||||||
|
static CrashQueue queue("/data/anr", "trace_" /* file_name_prefix */,
|
||||||
|
GetIntProperty("tombstoned.max_anr_count", 64),
|
||||||
|
4 /* max_concurrent_dumps */);
|
||||||
|
return &queue;
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<unique_fd, std::string> get_output() {
|
std::pair<unique_fd, std::string> get_output() {
|
||||||
unique_fd result;
|
unique_fd result;
|
||||||
std::string file_name = StringPrintf("%s%02d", file_name_prefix_.c_str(), next_artifact_);
|
std::string file_name = StringPrintf("%s%02d", file_name_prefix_.c_str(), next_artifact_);
|
||||||
|
|
@ -118,9 +150,6 @@ class CrashQueue {
|
||||||
|
|
||||||
void on_crash_completed() { --num_concurrent_dumps_; }
|
void on_crash_completed() { --num_concurrent_dumps_; }
|
||||||
|
|
||||||
static CrashQueue* const tombstone;
|
|
||||||
static CrashQueue* const java_trace;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void find_oldest_artifact() {
|
void find_oldest_artifact() {
|
||||||
size_t oldest_tombstone = 0;
|
size_t oldest_tombstone = 0;
|
||||||
|
|
@ -167,37 +196,6 @@ class CrashQueue {
|
||||||
// Whether java trace dumps are produced via tombstoned.
|
// Whether java trace dumps are produced via tombstoned.
|
||||||
static constexpr bool kJavaTraceDumpsEnabled = true;
|
static constexpr bool kJavaTraceDumpsEnabled = true;
|
||||||
|
|
||||||
/* static */ CrashQueue* const CrashQueue::tombstone =
|
|
||||||
new CrashQueue("/data/tombstones", "tombstone_" /* file_name_prefix */, 10 /* max_artifacts */,
|
|
||||||
1 /* max_concurrent_dumps */);
|
|
||||||
|
|
||||||
/* static */ CrashQueue* const CrashQueue::java_trace =
|
|
||||||
(kJavaTraceDumpsEnabled ? new CrashQueue("/data/anr", "trace_" /* file_name_prefix */,
|
|
||||||
64 /* max_artifacts */, 4 /* max_concurrent_dumps */)
|
|
||||||
: nullptr);
|
|
||||||
|
|
||||||
// Ownership of Crash is a bit messy.
|
|
||||||
// It's either owned by an active event that must have a timeout, or owned by
|
|
||||||
// queued_requests, in the case that multiple crashes come in at the same time.
|
|
||||||
struct Crash {
|
|
||||||
~Crash() { event_free(crash_event); }
|
|
||||||
|
|
||||||
unique_fd crash_fd;
|
|
||||||
pid_t crash_pid;
|
|
||||||
event* crash_event = nullptr;
|
|
||||||
std::string crash_path;
|
|
||||||
|
|
||||||
DebuggerdDumpType crash_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
static CrashQueue* get_crash_queue(const Crash* crash) {
|
|
||||||
if (crash->crash_type == kDebuggerdJavaBacktrace) {
|
|
||||||
return CrashQueue::java_trace;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CrashQueue::tombstone;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward declare the callbacks so they can be placed in a sensible order.
|
// Forward declare the callbacks so they can be placed in a sensible order.
|
||||||
static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int, void*);
|
static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int, void*);
|
||||||
static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg);
|
static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg);
|
||||||
|
|
@ -206,7 +204,7 @@ static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg);
|
||||||
static void perform_request(Crash* crash) {
|
static void perform_request(Crash* crash) {
|
||||||
unique_fd output_fd;
|
unique_fd output_fd;
|
||||||
if (!intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd)) {
|
if (!intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd)) {
|
||||||
std::tie(output_fd, crash->crash_path) = get_crash_queue(crash)->get_output();
|
std::tie(output_fd, crash->crash_path) = CrashQueue::for_crash(crash)->get_output();
|
||||||
}
|
}
|
||||||
|
|
||||||
TombstonedCrashPacket response = {
|
TombstonedCrashPacket response = {
|
||||||
|
|
@ -229,7 +227,7 @@ static void perform_request(Crash* crash) {
|
||||||
event_add(crash->crash_event, &timeout);
|
event_add(crash->crash_event, &timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
get_crash_queue(crash)->on_crash_started();
|
CrashQueue::for_crash(crash)->on_crash_started();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
@ -305,7 +303,7 @@ static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
|
||||||
|
|
||||||
LOG(INFO) << "received crash request for pid " << crash->crash_pid;
|
LOG(INFO) << "received crash request for pid " << crash->crash_pid;
|
||||||
|
|
||||||
if (get_crash_queue(crash)->maybe_enqueue_crash(crash)) {
|
if (CrashQueue::for_crash(crash)->maybe_enqueue_crash(crash)) {
|
||||||
LOG(INFO) << "enqueueing crash request for pid " << crash->crash_pid;
|
LOG(INFO) << "enqueueing crash request for pid " << crash->crash_pid;
|
||||||
} else {
|
} else {
|
||||||
perform_request(crash);
|
perform_request(crash);
|
||||||
|
|
@ -322,7 +320,7 @@ static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg) {
|
||||||
Crash* crash = static_cast<Crash*>(arg);
|
Crash* crash = static_cast<Crash*>(arg);
|
||||||
TombstonedCrashPacket request = {};
|
TombstonedCrashPacket request = {};
|
||||||
|
|
||||||
get_crash_queue(crash)->on_crash_completed();
|
CrashQueue::for_crash(crash)->on_crash_completed();
|
||||||
|
|
||||||
if ((ev & EV_READ) == 0) {
|
if ((ev & EV_READ) == 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -356,7 +354,7 @@ static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
CrashQueue* queue = get_crash_queue(crash);
|
CrashQueue* queue = CrashQueue::for_crash(crash);
|
||||||
delete crash;
|
delete crash;
|
||||||
|
|
||||||
// If there's something queued up, let them proceed.
|
// If there's something queued up, let them proceed.
|
||||||
|
|
@ -392,7 +390,7 @@ int main(int, char* []) {
|
||||||
intercept_manager = new InterceptManager(base, intercept_socket);
|
intercept_manager = new InterceptManager(base, intercept_socket);
|
||||||
|
|
||||||
evconnlistener* tombstone_listener = evconnlistener_new(
|
evconnlistener* tombstone_listener = evconnlistener_new(
|
||||||
base, crash_accept_cb, CrashQueue::tombstone, -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
|
base, crash_accept_cb, CrashQueue::for_tombstones(), -1, LEV_OPT_CLOSE_ON_FREE, crash_socket);
|
||||||
if (!tombstone_listener) {
|
if (!tombstone_listener) {
|
||||||
LOG(FATAL) << "failed to create evconnlistener for tombstones.";
|
LOG(FATAL) << "failed to create evconnlistener for tombstones.";
|
||||||
}
|
}
|
||||||
|
|
@ -405,7 +403,7 @@ int main(int, char* []) {
|
||||||
|
|
||||||
evutil_make_socket_nonblocking(java_trace_socket);
|
evutil_make_socket_nonblocking(java_trace_socket);
|
||||||
evconnlistener* java_trace_listener = evconnlistener_new(
|
evconnlistener* java_trace_listener = evconnlistener_new(
|
||||||
base, crash_accept_cb, CrashQueue::java_trace, -1, LEV_OPT_CLOSE_ON_FREE, java_trace_socket);
|
base, crash_accept_cb, CrashQueue::for_anrs(), -1, LEV_OPT_CLOSE_ON_FREE, java_trace_socket);
|
||||||
if (!java_trace_listener) {
|
if (!java_trace_listener) {
|
||||||
LOG(FATAL) << "failed to create evconnlistener for java traces.";
|
LOG(FATAL) << "failed to create evconnlistener for java traces.";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue