am 76feaf37: Merge "Append log data to tombstones"
* commit '76feaf37218b7fec02ade30c143884df8299697c': Append log data to tombstones
This commit is contained in:
commit
f26c6567d6
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue