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

Commit 3f9c22c3 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Add error reporting mechanism for failing Unwind."

parents 76ffa683 206a3b97
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