Add dumping of tombstones to dumpstate.
Dump only those tombstones modified within the last half an hour. Change-Id: I8ce836b2e19eba7a9c0c31a4f312f9a382526da7
This commit is contained in:
parent
76cbbc07ea
commit
1fe6107b66
@ -20,13 +20,13 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/capability.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/capability.h>
|
|
||||||
#include <sys/prctl.h>
|
|
||||||
|
|
||||||
#include <cutils/properties.h>
|
#include <cutils/properties.h>
|
||||||
|
|
||||||
@ -43,6 +43,36 @@ static const char *dump_traces_path = NULL;
|
|||||||
|
|
||||||
static char screenshot_path[PATH_MAX] = "";
|
static char screenshot_path[PATH_MAX] = "";
|
||||||
|
|
||||||
|
#define TOMBSTONE_DIR "/data/tombstones"
|
||||||
|
#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
|
||||||
|
/* Can accomodate a tombstone number up to 9999. */
|
||||||
|
#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
|
||||||
|
#define NUM_TOMBSTONES 10
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char name[TOMBSTONE_MAX_LEN];
|
||||||
|
int fd;
|
||||||
|
} tombstone_data_t;
|
||||||
|
|
||||||
|
static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
|
||||||
|
|
||||||
|
/* Get the fds of any tombstone that was modified in the last half an hour. */
|
||||||
|
static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
|
||||||
|
time_t thirty_minutes_ago = time(NULL) - 60*30;
|
||||||
|
for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
|
||||||
|
snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
|
||||||
|
int fd = open(data[i].name, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
|
||||||
|
struct stat st;
|
||||||
|
if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
|
||||||
|
(time_t) st.st_mtime >= thirty_minutes_ago) {
|
||||||
|
data[i].fd = fd;
|
||||||
|
} else {
|
||||||
|
close(fd);
|
||||||
|
data[i].fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* dumps the current system state to stdout */
|
/* dumps the current system state to stdout */
|
||||||
static void dumpstate() {
|
static void dumpstate() {
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
@ -116,7 +146,6 @@ static void dumpstate() {
|
|||||||
run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
|
run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
|
||||||
run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
|
run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
|
||||||
|
|
||||||
|
|
||||||
/* show the traces we collected in main(), if that was done */
|
/* show the traces we collected in main(), if that was done */
|
||||||
if (dump_traces_path != NULL) {
|
if (dump_traces_path != NULL) {
|
||||||
dump_file("VM TRACES JUST NOW", dump_traces_path);
|
dump_file("VM TRACES JUST NOW", dump_traces_path);
|
||||||
@ -128,10 +157,13 @@ static void dumpstate() {
|
|||||||
property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
|
property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
|
||||||
if (!anr_traces_path[0]) {
|
if (!anr_traces_path[0]) {
|
||||||
printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
|
printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
|
||||||
} else if (stat(anr_traces_path, &st)) {
|
} else {
|
||||||
|
int fd = open(anr_traces_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
|
||||||
|
if (fd < 0) {
|
||||||
printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
|
printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
dump_file("VM TRACES AT LAST ANR", anr_traces_path);
|
dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* slow traces for slow operations */
|
/* slow traces for slow operations */
|
||||||
@ -152,6 +184,18 @@ static void dumpstate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dumped = 0;
|
||||||
|
for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
|
||||||
|
if (tombstone_data[i].fd != -1) {
|
||||||
|
dumped = 1;
|
||||||
|
dump_file_from_fd("TOMBSTONE", tombstone_data[i].name, tombstone_data[i].fd);
|
||||||
|
tombstone_data[i].fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!dumped) {
|
||||||
|
printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
|
||||||
|
}
|
||||||
|
|
||||||
dump_file("NETWORK DEV INFO", "/proc/net/dev");
|
dump_file("NETWORK DEV INFO", "/proc/net/dev");
|
||||||
dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
|
dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
|
||||||
dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
|
dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
|
||||||
@ -404,6 +448,9 @@ int main(int argc, char *argv[]) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the tombstone fds here while we are running as root. */
|
||||||
|
get_tombstone_fds(tombstone_data);
|
||||||
|
|
||||||
/* switch to non-root user and group */
|
/* switch to non-root user and group */
|
||||||
gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
|
gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
|
||||||
AID_MOUNT, AID_INET, AID_NET_BW_STATS };
|
AID_MOUNT, AID_INET, AID_NET_BW_STATS };
|
||||||
|
@ -28,7 +28,10 @@ typedef void (for_each_pid_func)(int, const char *);
|
|||||||
typedef void (for_each_tid_func)(int, int, const char *);
|
typedef void (for_each_tid_func)(int, int, const char *);
|
||||||
|
|
||||||
/* prints the contents of a file */
|
/* prints the contents of a file */
|
||||||
int dump_file(const char *title, const char* path);
|
int dump_file(const char *title, const char *path);
|
||||||
|
|
||||||
|
/* prints the contents of the fd */
|
||||||
|
int dump_file_from_fd(const char *title, const char *path, int fd);
|
||||||
|
|
||||||
/* forks a command and waits for it to finish -- terminate args with NULL */
|
/* forks a command and waits for it to finish -- terminate args with NULL */
|
||||||
int run_command(const char *title, int timeout_seconds, const char *command, ...);
|
int run_command(const char *title, int timeout_seconds, const char *command, ...);
|
||||||
@ -64,7 +67,7 @@ void do_dmesg();
|
|||||||
void dump_route_tables();
|
void dump_route_tables();
|
||||||
|
|
||||||
/* Play a sound via Stagefright */
|
/* Play a sound via Stagefright */
|
||||||
void play_sound(const char* path);
|
void play_sound(const char *path);
|
||||||
|
|
||||||
/* Implemented by libdumpstate_board to dump board-specific info */
|
/* Implemented by libdumpstate_board to dump board-specific info */
|
||||||
void dumpstate_board();
|
void dumpstate_board();
|
||||||
|
@ -210,8 +210,7 @@ void do_showmap(int pid, const char *name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* prints the contents of a file */
|
/* prints the contents of a file */
|
||||||
int dump_file(const char *title, const char* path) {
|
int dump_file(const char *title, const char *path) {
|
||||||
char buffer[32768];
|
|
||||||
int fd = open(path, O_RDONLY);
|
int fd = open(path, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
int err = errno;
|
int err = errno;
|
||||||
@ -220,6 +219,11 @@ int dump_file(const char *title, const char* path) {
|
|||||||
if (title) printf("\n");
|
if (title) printf("\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
return dump_file_from_fd(title, path, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dump_file_from_fd(const char *title, const char *path, int fd) {
|
||||||
|
char buffer[32768];
|
||||||
|
|
||||||
if (title) printf("------ %s (%s", title, path);
|
if (title) printf("------ %s (%s", title, path);
|
||||||
|
|
||||||
@ -243,8 +247,8 @@ int dump_file(const char *title, const char* path) {
|
|||||||
}
|
}
|
||||||
if (ret <= 0) break;
|
if (ret <= 0) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (!newline) printf("\n");
|
if (!newline) printf("\n");
|
||||||
if (title) printf("\n");
|
if (title) printf("\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user