OSDN Git Service

Add dumping of tombstones to dumpstate.
authorChristopher Ferris <cferris@google.com>
Tue, 22 Jul 2014 23:08:19 +0000 (16:08 -0700)
committerChristopher Ferris <cferris@google.com>
Wed, 23 Jul 2014 23:33:01 +0000 (16:33 -0700)
Dump only those tombstones modified within the last half an hour.

Change-Id: I8ce836b2e19eba7a9c0c31a4f312f9a382526da7

cmds/dumpstate/dumpstate.c
cmds/dumpstate/dumpstate.h
cmds/dumpstate/utils.c

index c6a2a0d..c23a9e8 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <unistd.h>
-#include <sys/capability.h>
-#include <sys/prctl.h>
 
 #include <cutils/properties.h>
 
@@ -43,6 +43,36 @@ static const char *dump_traces_path = NULL;
 
 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 */
 static void dumpstate() {
     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("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
 
-
     /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != NULL) {
         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, "");
     if (!anr_traces_path[0]) {
         printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
-    } else if (stat(anr_traces_path, &st)) {
-        printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
     } else {
-        dump_file("VM TRACES AT LAST ANR", anr_traces_path);
+      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));
+      } else {
+          dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
+      }
     }
 
     /* 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("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");
@@ -404,6 +448,9 @@ int main(int argc, char *argv[]) {
         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 */
     gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
             AID_MOUNT, AID_INET, AID_NET_BW_STATS };
index 6906dcf..e75da2d 100644 (file)
@@ -28,7 +28,10 @@ typedef void (for_each_pid_func)(int, const char *);
 typedef void (for_each_tid_func)(int, int, const char *);
 
 /* 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 */
 int run_command(const char *title, int timeout_seconds, const char *command, ...);
@@ -64,7 +67,7 @@ void do_dmesg();
 void dump_route_tables();
 
 /* Play a sound via Stagefright */
-void play_sound(const charpath);
+void play_sound(const char *path);
 
 /* Implemented by libdumpstate_board to dump board-specific info */
 void dumpstate_board();
index 9451417..56287a0 100644 (file)
@@ -210,8 +210,7 @@ void do_showmap(int pid, const char *name) {
 }
 
 /* prints the contents of a file */
-int dump_file(const char *title, const char* path) {
-    char buffer[32768];
+int dump_file(const char *title, const char *path) {
     int fd = open(path, O_RDONLY);
     if (fd < 0) {
         int err = errno;
@@ -220,6 +219,11 @@ int dump_file(const char *title, const char* path) {
         if (title) printf("\n");
         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);
 
@@ -243,8 +247,8 @@ int dump_file(const char *title, const char* path) {
         }
         if (ret <= 0) break;
     }
-
     close(fd);
+
     if (!newline) printf("\n");
     if (title) printf("\n");
     return 0;