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

Commit 7c970c8a authored by Christopher Ferris's avatar Christopher Ferris Committed by android-build-merger
Browse files

Add error reporting mechanism for failing Unwind.

am: c463ba45

* commit 'c463ba45':
  Add error reporting mechanism for failing Unwind.
parents f7b6d9ce c463ba45
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -91,7 +91,8 @@ static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) {
  if (backtrace->Unwind(0)) {
    dump_backtrace_to_log(backtrace.get(), log, "  ");
  } else {
    ALOGE("Unwind failed: tid = %d", tid);
    ALOGE("Unwind failed: tid = %d: %s", tid,
          backtrace->GetErrorString(backtrace->GetError()).c_str());
  }
}

+24 −0
Original line number Diff line number Diff line
@@ -34,6 +34,24 @@ typedef uint64_t word_t;
typedef uint32_t word_t;
#endif

enum BacktraceUnwindError : uint32_t {
  BACKTRACE_UNWIND_NO_ERROR,
  // Something failed while trying to perform the setup to begin the unwind.
  BACKTRACE_UNWIND_ERROR_SETUP_FAILED,
  // There is no map information to use with the unwind.
  BACKTRACE_UNWIND_ERROR_MAP_MISSING,
  // An error occurred that indicates a programming error.
  BACKTRACE_UNWIND_ERROR_INTERNAL,
  // The thread to unwind has disappeared before the unwind can begin.
  BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST,
  // The thread to unwind has not responded to a signal in a timely manner.
  BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT,
  // Attempt to do an unsupported operation.
  BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION,
  // Attempt to do an offline unwind without a context.
  BACKTRACE_UNWIND_ERROR_NO_CONTEXT,
};

struct backtrace_frame_data_t {
  size_t num;             // The current fame number.
  uintptr_t pc;           // The absolute pc.
@@ -127,6 +145,10 @@ public:

  BacktraceMap* GetMap() { return map_; }

  BacktraceUnwindError GetError() { return error_; }

  std::string GetErrorString(BacktraceUnwindError error);

protected:
  Backtrace(pid_t pid, pid_t tid, BacktraceMap* map);

@@ -145,6 +167,8 @@ protected:
  bool map_shared_;

  std::vector<backtrace_frame_data_t> frames_;

  BacktraceUnwindError error_;
};

#endif // _BACKTRACE_BACKTRACE_H
+21 −0
Original line number Diff line number Diff line
@@ -148,3 +148,24 @@ Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) {
    return new UnwindPtrace(pid, tid, map);
  }
}

std::string Backtrace::GetErrorString(BacktraceUnwindError error) {
  switch (error) {
  case BACKTRACE_UNWIND_NO_ERROR:
    return "No error";
  case BACKTRACE_UNWIND_ERROR_SETUP_FAILED:
    return "Setup failed";
  case BACKTRACE_UNWIND_ERROR_MAP_MISSING:
    return "No map found";
  case BACKTRACE_UNWIND_ERROR_INTERNAL:
    return "Internal libbacktrace error, please submit a bugreport";
  case BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST:
    return "Thread doesn't exist";
  case BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT:
    return "Thread has not repsonded to signal in time";
  case BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION:
    return "Attempt to use an unsupported feature";
  case BACKTRACE_UNWIND_ERROR_NO_CONTEXT:
    return "Attempt to do an offline unwind without a context";
  }
}
+20 −2
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
#include <ucontext.h>
#include <unistd.h>

#include <stdlib.h>

#include <string>

#include <backtrace/Backtrace.h>
@@ -65,9 +67,11 @@ size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
  if (GetMap() == nullptr) {
    // Without a map object, we can't do anything.
    error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
    return false;
  }

  error_ = BACKTRACE_UNWIND_NO_ERROR;
  if (ucontext) {
    return UnwindFromContext(num_ignore_frames, ucontext);
  }
@@ -138,11 +142,19 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
    BACK_LOGE("sigaction failed: %s", strerror(errno));
    ThreadEntry::Remove(entry);
    pthread_mutex_unlock(&g_sigaction_mutex);
    error_ = BACKTRACE_UNWIND_ERROR_INTERNAL;
    return false;
  }

  if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
    BACK_LOGE("tgkill %d failed: %s", Tid(), strerror(errno));
    // Do not emit an error message, this might be expected. Set the
    // error and let the caller decide.
    if (errno == ESRCH) {
      error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
    } else {
      error_ = BACKTRACE_UNWIND_ERROR_INTERNAL;
    }

    sigaction(THREAD_SIGNAL, &oldact, nullptr);
    ThreadEntry::Remove(entry);
    pthread_mutex_unlock(&g_sigaction_mutex);
@@ -183,8 +195,14 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) {
      BACK_LOGW("Timed out waiting for signal handler to indicate it finished.");
    }
  } else {
    // Check to see if the thread has disappeared.
    if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) {
      error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
    } else {
      error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT;
      BACK_LOGE("Timed out waiting for signal handler to get ucontext data.");
    }
  }

  ThreadEntry::Remove(entry);

+3 −0
Original line number Diff line number Diff line
@@ -129,9 +129,11 @@ static unw_accessors_t accessors = {
bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
  if (context == nullptr) {
    BACK_LOGW("The context is needed for offline backtracing.");
    error_ = BACKTRACE_UNWIND_ERROR_NO_CONTEXT;
    return false;
  }
  context_ = context;
  error_ = BACKTRACE_UNWIND_NO_ERROR;

  unw_addr_space_t addr_space = unw_create_addr_space(&accessors, 0);
  unw_cursor_t cursor;
@@ -139,6 +141,7 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
  if (ret != 0) {
    BACK_LOGW("unw_init_remote failed %d", ret);
    unw_destroy_addr_space(addr_space);
    error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
    return false;
  }
  size_t num_frames = 0;
Loading