am 76feaf37: Merge "Append log data to tombstones"

* commit '76feaf37218b7fec02ade30c143884df8299697c':
  Append log data to tombstones
This commit is contained in:
Andy McFadden 2011-10-14 10:46:34 -07:00 committed by Android Git Automerger
commit f26c6567d6
1 changed files with 103 additions and 0 deletions

View File

@ -31,6 +31,7 @@
#include <cutils/sockets.h>
#include <cutils/logd.h>
#include <cutils/logger.h>
#include <cutils/properties.h>
#include <linux/input.h>
@ -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)
@ -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;
}