Add ANR monitor 96/293496/1
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 31 May 2023 00:39:19 +0000 (00:39 +0000)
committerHwankyu Jhun <h.jhun@samsung.com>
Wed, 31 May 2023 00:42:27 +0000 (00:42 +0000)
For debug the main thread state when the application is the deadlock state,
this patch adds an AnrMonitor class. While getting SIGRTANR(SIGRTMIN + 3) signal,
the application core prints the backtrace of the main thread of the application.

Change-Id: Ib820d0afe0b06f3909182bc48dc66dddb6b49918
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
tizen-cpp/app-core-cpp/app_core_base.cc

index 18e6e70..9b41cb0 100644 (file)
@@ -31,6 +31,7 @@
 #include <locale.h>
 #include <malloc.h>
 #include <sensor_internal.h>
+#include <signal.h>
 #include <stdbool.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include "common/glib_private.hh"
 #include "common/log_private.hh"
 
+#define SIGRTANR (SIGRTMIN + 3)
+#undef _ERR
+#define _ERR(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
+
 extern "C" void aul_finalize();
 namespace tizen_cpp {
 
@@ -63,6 +68,30 @@ namespace {
 
 constexpr const int BACKTRACE_BUFFER_SIZE = 128;
 
+void PrintBacktrace() {
+  char* buffer[BACKTRACE_BUFFER_SIZE];
+  int nptrs = backtrace(reinterpret_cast<void**>(buffer),
+      BACKTRACE_BUFFER_SIZE);
+  _ERR("backtrace() returned %d addresses", nptrs - 4);
+
+  // To print numbers, we use backtrace_symbols() instead of backtrace_symbols_fd().
+  // If there is an issues related to the memory, we cannot use backtrace_symbols().
+  // backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
+  char** strings = backtrace_symbols(reinterpret_cast<void**>(buffer), nptrs);
+  if (strings == nullptr) {
+    perror("backtrace_symbols");
+    return;
+  }
+
+  Dl_info info;
+  for (int i = 4; i < nptrs; ++i) {
+    dladdr(buffer[i], &info);
+    _ERR("[%3d] %s %s",
+        i - 4, info.dli_sname ? info.dli_sname : "?", strings[i]);
+  }
+  free(strings);
+}
+
 class ExitHandler {
  public:
   ExitHandler() {
@@ -74,36 +103,50 @@ class ExitHandler {
     if (status != 127)
       return;
 
-    char* buffer[BACKTRACE_BUFFER_SIZE];
-    int nptrs = backtrace(reinterpret_cast<void**>(buffer),
-        BACKTRACE_BUFFER_SIZE);
-    fprintf(stderr, "%s backtrace() returned %d addesses\n",
-        __FUNCTION__, nptrs);
-
-    // To print numbers, we use backtrace_symbols() instead of backtrace_symbols_fd().
-    // If there is an issues related to the memory, we cannot use backtrace_symbols().
-    // backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
-    char** strings = backtrace_symbols(reinterpret_cast<void**>(buffer), nptrs);
-    if (strings == nullptr) {
-      perror("backtrace_symbols");
-      return;
-    }
-
-    Dl_info info;
-    for (int i = 0; i < nptrs; ++i) {
-      dladdr(buffer[i], &info);
-      fprintf(stderr, "[%3d] %s %s\n",
-          i, info.dli_sname ? info.dli_sname : "?", strings[i]);
-    }
-    free(strings);
+    PrintBacktrace();
 
-    fprintf(stderr, "%s(%d) abort()\n", __FUNCTION__, __LINE__);
+    _ERR("%s(%d) abort()", __FUNCTION__, __LINE__);
     abort();
   }
 };
 
 ExitHandler exit_handler;
 
+class AnrMonitor {
+ public:
+  AnrMonitor() {
+    struct sigaction action;
+    memset(&action, '\0', sizeof(action));
+    sigemptyset(&action.sa_mask);
+    action.sa_flags = SA_RESTART;
+    action.sa_handler = SignalHandler;
+
+    if (sigaction(SIGRTANR, &action, &old_action_) != 0)
+      _E("sigaction() is failed. errno(%d)", errno);
+  }
+
+  ~AnrMonitor() {
+    if (sigaction(SIGRTANR, &old_action_, nullptr) != 0)
+      _W("sigaction() is failed. errno(%d)", errno);
+  }
+
+ private:
+  static void SignalHandler(int signo) {
+    static unsigned int count;
+    _ERR("===================================================================");
+    _ERR("=================== Application Not Responding ====================");
+    PrintBacktrace();
+    _ERR("============== Application did not respond %d times ===============",
+        ++count);
+    _ERR("===================================================================");
+  }
+
+ private:
+  struct sigaction old_action_;
+};
+
+AnrMonitor anr_monitor;
+
 enum TizenProfile {
   Unknown = 0x00,
   Mobile = 0x01,