Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22b5cef1 authored by Mark Salyzyn's avatar Mark Salyzyn
Browse files

debuggerd: Incorporate liblog reading API

(cherry picked from commit a63f927c)

Change-Id: Ic26e9dba3b45c827d122b03e34cc4a5bd48f7deb
parent 4295841e
Loading
Loading
Loading
Loading
+38 −59
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 * Copyright (C) 2012-2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@

#include <private/android_filesystem_config.h>

#include <log/log.h>
#include <log/logger.h>
#include <cutils/properties.h>

@@ -453,43 +454,40 @@ static bool dump_sibling_thread_report(
// 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.
//
// If "tailOnly" is set, we only print the last few lines.
static void dump_log_file(log_t* log, pid_t pid, const char* filename, bool tailOnly) {
// If "tail" is set, we only print the last few lines.
static void dump_log_file(log_t* log, pid_t pid, const char* filename,
  unsigned int tail) {
  bool first = true;
  struct logger_list *logger_list;

  // circular buffer, for "tailOnly" mode
  const int kShortLogMaxLines = 5;
  const int kShortLogLineLen = 256;
  char shortLog[kShortLogMaxLines][kShortLogLineLen];
  int shortLogCount = 0;
  int shortLogNext = 0;
  logger_list = android_logger_list_open(
    android_name_to_log_id(filename), O_RDONLY | O_NONBLOCK, tail, pid);

  int logfd = open(filename, O_RDONLY | O_NONBLOCK);
  if (logfd < 0) {
  if (!logger_list) {
    XLOG("Unable to open %s: %s\n", filename, strerror(errno));
    return;
  }

  union {
    unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
    struct logger_entry entry;
  } log_entry;
  struct log_msg log_entry;

  while (true) {
    ssize_t actual = read(logfd, log_entry.buf, LOGGER_ENTRY_MAX_LEN);
    ssize_t actual = android_logger_list_read(logger_list, &log_entry);

    if (actual < 0) {
      if (errno == EINTR) {
      if (actual == -EINTR) {
        // interrupted by signal, retry
        continue;
      } else if (errno == EAGAIN) {
      } else if (actual == -EAGAIN) {
        // non-blocking EOF; we're done
        break;
      } else {
        _LOG(log, 0, "Error while reading log: %s\n", strerror(errno));
        _LOG(log, 0, "Error while reading log: %s\n",
          strerror(-actual));
        break;
      }
    } else if (actual == 0) {
      _LOG(log, 0, "Got zero bytes while reading log: %s\n", strerror(errno));
      _LOG(log, 0, "Got zero bytes while reading log: %s\n",
        strerror(errno));
      break;
    }

@@ -497,7 +495,7 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, bool tail
    // 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;
    struct logger_entry* entry = &log_entry.entry_v1;

    if (entry->pid != static_cast<int32_t>(pid)) {
      // wrong pid, ignore
@@ -505,7 +503,8 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, bool tail
    }

    if (first) {
      _LOG(log, 0, "--------- %slog %s\n", tailOnly ? "tail end of " : "", filename);
      _LOG(log, 0, "--------- %slog %s\n",
        tail ? "tail end of " : "", filename);
      first = false;
    }

@@ -517,9 +516,14 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, bool tail
    // 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];
    char* tag = entry->msg + 1;
    char* msg = tag + strlen(tag) + 1;
    unsigned hdr_size = log_entry.entry.hdr_size;
    if (!hdr_size) {
      hdr_size = sizeof(log_entry.entry_v1);
    }
    char* msg = (char *)log_entry.buf + hdr_size;
    unsigned char prio = msg[0];
    char* tag = msg + 1;
    msg = tag + strlen(tag) + 1;

    // consume any trailing newlines
    char* eatnl = msg + strlen(msg) - 1;
@@ -536,44 +540,19 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename, bool tail
    ptm = localtime_r(&sec, &tmBuf);
    strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);

    if (tailOnly) {
      snprintf(shortLog[shortLogNext], kShortLogLineLen,
               "%s.%03d %5d %5d %c %-8s: %s",
    _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
       timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
       prioChar, tag, msg);
      shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
      shortLogCount++;
    } else {
      _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
           timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, prioChar, tag, msg);
    }
  }

  if (tailOnly) {
    int i;

    // If we filled the buffer, we want to start at "next", which has
    // the oldest entry.  If we didn't, we want to start at zero.
    if (shortLogCount < kShortLogMaxLines) {
      shortLogNext = 0;
    } else {
      shortLogCount = kShortLogMaxLines;  // cap at window size
    }

    for (i = 0; i < shortLogCount; i++) {
      _LOG(log, 0, "%s\n", shortLog[shortLogNext]);
      shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
    }
  }

  close(logfd);
  android_logger_list_free(logger_list);
}

// 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(log_t* log, pid_t pid, bool tailOnly) {
  dump_log_file(log, pid, "/dev/log/system", tailOnly);
  dump_log_file(log, pid, "/dev/log/main", tailOnly);
static void dump_logs(log_t* log, pid_t pid, unsigned tail) {
  dump_log_file(log, pid, "system", tail);
  dump_log_file(log, pid, "main", tail);
}

static void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t address) {
@@ -649,7 +628,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
  }

  if (want_logs) {
    dump_logs(log, pid, true);
    dump_logs(log, pid, 5);
  }

  bool detach_failed = false;
@@ -661,7 +640,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
  delete map;

  if (want_logs) {
    dump_logs(log, pid, false);
    dump_logs(log, pid, 0);
  }

  // send EOD to the Activity Manager, then wait for its ack to avoid racing ahead