Loading debuggerd/debuggerd.c +103 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <cutils/sockets.h> #include <cutils/logd.h> #include <cutils/logger.h> #include <cutils/properties.h> #include <linux/input.h> Loading Loading @@ -413,6 +414,101 @@ static bool dump_sibling_thread_report(int tfd, unsigned pid, unsigned tid) return need_cleanup != 0; } /* * Reads the contents of the specified log device, filters out the entries * that don't match the specified pid, and writes them to the tombstone file. */ static void dump_log_file(int tfd, unsigned pid, const char* filename) { int logfd = open(filename, O_RDONLY | O_NONBLOCK); if (logfd < 0) { XLOG("Unable to open %s: %s\n", filename, strerror(errno)); return; } _LOG(tfd, true, "--------- log %s\n", filename); union { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; struct logger_entry entry; } log_entry; while (true) { ssize_t actual = read(logfd, log_entry.buf, LOGGER_ENTRY_MAX_LEN); if (actual < 0) { if (errno == EINTR) { /* interrupted by signal, retry */ continue; } else if (errno == EAGAIN) { /* non-blocking EOF; we're done */ break; } else { _LOG(tfd, true, "Error while reading log: %s\n", strerror(errno)); break; } } else if (actual == 0) { _LOG(tfd, true, "Got zero bytes while reading log: %s\n", strerror(errno)); break; } /* * NOTE: if you XLOG something here, this will spin forever, * because you will be writing as fast as you're reading. Any * high-frequency debug diagnostics should just be written to * the tombstone file. */ struct logger_entry* entry = &log_entry.entry; if (entry->pid != (int32_t) pid) { /* wrong pid, ignore */ continue; } /* * Msg format is: <priority:1><tag:N>\0<message:N>\0 * * We want to display it in the same format as "logcat -v threadtime" * (although in this case the pid is redundant). * * TODO: scan for line breaks ('\n') and display each text line * on a separate line, prefixed with the header, like logcat does. */ static const char* kPrioChars = "!.VDIWEFS"; unsigned char prio = entry->msg[0]; const char* tag = entry->msg + 1; const char* msg = tag + strlen(tag) + 1; log_entry.entry.msg[entry->len] = '\0'; char timeBuf[32]; time_t sec = (time_t) entry->sec; struct tm tmBuf; struct tm* ptm; ptm = localtime_r(&sec, &tmBuf); strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm); _LOG(tfd, true, "%s.%03ld %5d %5d %c %-8s: %s\n", timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, (prio < strlen(kPrioChars) ? kPrioChars[prio] : '?'), tag, msg); } close(logfd); } /* * Dumps the logs generated by the specified pid to the tombstone, from both * "system" and "main" log devices. Ideally we'd interleave the output. */ static void dump_logs(int tfd, unsigned pid) { dump_log_file(tfd, pid, "/dev/log/system"); dump_log_file(tfd, pid, "/dev/log/main"); } /* Return true if some thread is not detached cleanly */ static bool engrave_tombstone(unsigned pid, unsigned tid, int debug_uid, int signal) Loading @@ -437,6 +533,13 @@ static bool engrave_tombstone(unsigned pid, unsigned tid, int debug_uid, need_cleanup = dump_sibling_thread_report(fd, pid, tid); } /* don't copy log to tombstone unless this is a dev device */ char value[PROPERTY_VALUE_MAX]; property_get("ro.debuggable", value, "0"); if (value[0] == '1') { dump_logs(fd, pid); } close(fd); return need_cleanup; } Loading Loading
debuggerd/debuggerd.c +103 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <cutils/sockets.h> #include <cutils/logd.h> #include <cutils/logger.h> #include <cutils/properties.h> #include <linux/input.h> Loading Loading @@ -413,6 +414,101 @@ static bool dump_sibling_thread_report(int tfd, unsigned pid, unsigned tid) return need_cleanup != 0; } /* * Reads the contents of the specified log device, filters out the entries * that don't match the specified pid, and writes them to the tombstone file. */ static void dump_log_file(int tfd, unsigned pid, const char* filename) { int logfd = open(filename, O_RDONLY | O_NONBLOCK); if (logfd < 0) { XLOG("Unable to open %s: %s\n", filename, strerror(errno)); return; } _LOG(tfd, true, "--------- log %s\n", filename); union { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; struct logger_entry entry; } log_entry; while (true) { ssize_t actual = read(logfd, log_entry.buf, LOGGER_ENTRY_MAX_LEN); if (actual < 0) { if (errno == EINTR) { /* interrupted by signal, retry */ continue; } else if (errno == EAGAIN) { /* non-blocking EOF; we're done */ break; } else { _LOG(tfd, true, "Error while reading log: %s\n", strerror(errno)); break; } } else if (actual == 0) { _LOG(tfd, true, "Got zero bytes while reading log: %s\n", strerror(errno)); break; } /* * NOTE: if you XLOG something here, this will spin forever, * because you will be writing as fast as you're reading. Any * high-frequency debug diagnostics should just be written to * the tombstone file. */ struct logger_entry* entry = &log_entry.entry; if (entry->pid != (int32_t) pid) { /* wrong pid, ignore */ continue; } /* * Msg format is: <priority:1><tag:N>\0<message:N>\0 * * We want to display it in the same format as "logcat -v threadtime" * (although in this case the pid is redundant). * * TODO: scan for line breaks ('\n') and display each text line * on a separate line, prefixed with the header, like logcat does. */ static const char* kPrioChars = "!.VDIWEFS"; unsigned char prio = entry->msg[0]; const char* tag = entry->msg + 1; const char* msg = tag + strlen(tag) + 1; log_entry.entry.msg[entry->len] = '\0'; char timeBuf[32]; time_t sec = (time_t) entry->sec; struct tm tmBuf; struct tm* ptm; ptm = localtime_r(&sec, &tmBuf); strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm); _LOG(tfd, true, "%s.%03ld %5d %5d %c %-8s: %s\n", timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, (prio < strlen(kPrioChars) ? kPrioChars[prio] : '?'), tag, msg); } close(logfd); } /* * Dumps the logs generated by the specified pid to the tombstone, from both * "system" and "main" log devices. Ideally we'd interleave the output. */ static void dump_logs(int tfd, unsigned pid) { dump_log_file(tfd, pid, "/dev/log/system"); dump_log_file(tfd, pid, "/dev/log/main"); } /* Return true if some thread is not detached cleanly */ static bool engrave_tombstone(unsigned pid, unsigned tid, int debug_uid, int signal) Loading @@ -437,6 +533,13 @@ static bool engrave_tombstone(unsigned pid, unsigned tid, int debug_uid, need_cleanup = dump_sibling_thread_report(fd, pid, tid); } /* don't copy log to tombstone unless this is a dev device */ char value[PROPERTY_VALUE_MAX]; property_get("ro.debuggable", value, "0"); if (value[0] == '1') { dump_logs(fd, pid); } close(fd); return need_cleanup; } Loading