From 9ef69b098c7f3864c447e17eb3666293628e75db Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 31 May 2023 00:39:19 +0000 Subject: [PATCH] Add ANR monitor 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 --- tizen-cpp/app-core-cpp/app_core_base.cc | 89 ++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/tizen-cpp/app-core-cpp/app_core_base.cc b/tizen-cpp/app-core-cpp/app_core_base.cc index 18e6e70..9b41cb0 100644 --- a/tizen-cpp/app-core-cpp/app_core_base.cc +++ b/tizen-cpp/app-core-cpp/app_core_base.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,10 @@ #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(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(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(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(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, -- 2.7.4