debug utility : dump backtrace whenever exit called or signal catched 95/17895/4
authorGeunhae LEE <geunhae.lee@samsung.com>
Wed, 12 Mar 2014 06:44:58 +0000 (15:44 +0900)
committerGeunhae LEE <geunhae.lee@samsung.com>
Mon, 17 Mar 2014 06:32:47 +0000 (15:32 +0900)
 - tested on both Linux and Windows
 - stack trace is printed out in emulator.log by class of err
 - it only print stack trace for thread which either calls exit or catchs signals

Change-Id: I45258234af329889226badb8e8455d355ded4de6
Signed-off-by: Geunhae LEE <geunhae.lee@samsung.com>
tizen/src/emulator.c
tizen/src/maru_err_table.c
tizen/src/maru_err_table.h
util/qemu-thread-posix.c

index a6b7701e4e14d1a7bc6c7c9f721cbdb098a79198..86441e6af51090b33fac907c434d4ac42c704c0b 100644 (file)
@@ -563,6 +563,7 @@ static int emulator_main(int argc, char *argv[])
 #ifndef CONFIG_DARWIN
 int main(int argc, char *argv[])
 {
+    maru_register_exception_handler();
     return emulator_main(argc, argv);
 }
 #else
index 29c5ea9f39cb51380e300444f04c908a6db0b7b3..3e695c892f616e4d1c900d5f3ce2152ff8f38284 100644 (file)
@@ -31,6 +31,7 @@
 #include "qemu-common.h"
 #include "maru_common.h"
 #include "maru_err_table.h"
+#include "debug_ch.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,6 +44,8 @@
 #include <execinfo.h>
 #endif
 
+
+MULTI_DEBUG_CHANNEL(qemu, backtrace);
 /* This table must match the enum definition */
 static char _maru_string_table[][JAVA_MAX_COMMAND_LENGTH] = {
     /* 0 */ "",
@@ -62,6 +65,16 @@ A problem caused the program to stop working correctly.",
 static int maru_exit_status = MARU_EXIT_NORMAL;
 static char maru_exit_msg[JAVA_MAX_COMMAND_LENGTH] = { 0, };
 
+#ifdef CONFIG_WIN32
+static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter;
+#endif
+
+#ifdef CONFIG_LINUX
+static pthread_spinlock_t siglock;
+void maru_sighandler(int sig);
+#endif
+
+
 void maru_register_exit_msg(int maru_exit_index, char const *const additional_msg)
 {
     int len = 0;
@@ -117,10 +130,16 @@ The time of internal heartbeat has expired.\n");
 
 void maru_atexit(void)
 {
+
+#if 0
     if (maru_exit_status != MARU_EXIT_NORMAL || strlen(maru_exit_msg) != 0) {
         maru_dump_backtrace(NULL, 0);
         start_simple_client(maru_exit_msg);
     }
+#else
+    INFO("call exit codes\n");
+    maru_dump_backtrace(NULL, 0);
+#endif
 }
 
 char *maru_convert_path(char *msg, const char *path)
@@ -253,9 +272,8 @@ void maru_dump_backtrace(void *ptr, int depth)
     currentFrame.pReturnAddr = ((struct frame_layout *)pTopFrame)->pReturnAddr;
     pCurrentFrame = (struct frame_layout *)pTopFrame;
 
-    fprintf(stderr, "\nBacktrace Dump Start :\n");
+    ERR("\nBacktrace Dump Start :\n");
     if (pContext) {
-        fprintf(stderr, "[%02d]Addr = 0x%p", nCount, ((PCONTEXT)pContext)->Eip);
         memset(module_buf, 0, sizeof(module_buf));
         hModule = aqua_get_module_handle((DWORD)((PCONTEXT)pContext)->Eip);
         if (hModule) {
@@ -263,7 +281,7 @@ void maru_dump_backtrace(void *ptr, int depth)
                 memset(module_buf, 0, sizeof(module_buf));
             }
         }
-        fprintf(stderr, " : %s\n", aqua_get_filename_from_path(module_buf));
+        ERR("[%02d]Addr = 0x%p : %s\n", nCount, ((PCONTEXT)pContext)->Eip, aqua_get_filename_from_path(module_buf));
         nCount++;
     }
 
@@ -273,7 +291,6 @@ void maru_dump_backtrace(void *ptr, int depth)
             break;
         }
 
-        fprintf(stderr, "[%02d]Addr = 0x%p", nCount, currentFrame.pReturnAddr);
         memset(module_buf, 0, sizeof(module_buf));
         hModule = aqua_get_module_handle((DWORD)currentFrame.pReturnAddr);
         if (hModule) {
@@ -281,7 +298,7 @@ void maru_dump_backtrace(void *ptr, int depth)
                 memset(module_buf, 0, sizeof(module_buf));
             }
         }
-        fprintf(stderr, " : %s\n", aqua_get_filename_from_path(module_buf));
+        ERR("[%02d]Addr = 0x%p : %s\n", nCount, currentFrame.pReturnAddr, aqua_get_filename_from_path(module_buf));
 
     if (!ReadProcessMemory(GetCurrentProcess(), currentFrame.pNext,
             (void *)&currentFrame, sizeof(struct frame_layout), NULL)) {
@@ -297,25 +314,88 @@ void maru_dump_backtrace(void *ptr, int depth)
         nCount++;
     }
 #else
-    int i, ndepth;
     void *trace[1024];
-    char **symbols;
+    int ndepth = backtrace(trace, 1024);
+    ERR("Backtrace depth is %d.\n", ndepth);
 
-    fprintf(stderr, "\n Backtrace Dump Start :\n");
+    backtrace_symbols_fd(trace, ndepth, fileno(stderr));
+#endif
+}
 
-    ndepth = backtrace(trace, 1024);
-    fprintf(stderr, "Backtrace depth is %d.\n", ndepth);
+#ifdef CONFIG_WIN32
+static LONG maru_unhandled_exception_filter(PEXCEPTION_POINTERS pExceptionInfo){
+    char module_buf[1024];
+    DWORD dwException = pExceptionInfo->ExceptionRecord->ExceptionCode;
+    ERR("%d\n ", (int)dwException);
 
-    symbols = backtrace_symbols(trace, ndepth);
-    if (symbols == NULL) {
-        fprintf(stderr, "'backtrace_symbols()' return error");
-        return;
-    }
+    PEXCEPTION_RECORD pExceptionRecord;
+    HMODULE hModule;
+    PCONTEXT pContext;
 
-    for (i = 0; i < ndepth; i++) {
-        fprintf(stderr, "%s\n", symbols[i]);
+    pExceptionRecord = pExceptionInfo->ExceptionRecord;
+
+    memset(module_buf, 0, sizeof(module_buf));
+    hModule = aqua_get_module_handle((DWORD)pExceptionRecord->ExceptionAddress);
+    if(hModule){
+        if(!GetModuleFileNameA(hModule, module_buf, sizeof(module_buf))){
+            memset(module_buf, 0, sizeof(module_buf));
+        }
     }
-    free(symbols);
+
+    ERR("Exception [%X] occured at %s:0x%08x, running badaEmulator.exe\n",
+        pExceptionRecord->ExceptionCode,
+        aqua_get_filename_from_path(module_buf),
+        pExceptionRecord->ExceptionAddress
+       );
+
+
+    pContext = pExceptionInfo->ContextRecord;
+    maru_dump_backtrace(pContext, 0);
+
+
+
+
+
+    _exit(0);
+    return EXCEPTION_CONTINUE_SEARCH;
+}
 #endif
+
+#ifdef CONFIG_LINUX
+void maru_sighandler(int sig)
+{
+    pthread_spin_lock(&siglock);
+    ERR("Got signal %d\n", sig);
+    maru_dump_backtrace(NULL, 0);
+    pthread_spin_unlock(&siglock);
+    _exit(0);
 }
+#endif
+
 
+void maru_register_exception_handler(void)
+{
+#ifdef CONFIG_WIN32
+    prevExceptionFilter = SetUnhandledExceptionFilter(maru_unhandled_exception_filter);
+#else
+
+    void *trace[1];
+    struct sigaction sa;
+
+    // make dummy call to explicitly load glibc library
+    backtrace(trace, 1);
+
+    pthread_spin_init(&siglock,0);
+    sa.sa_handler = (void*) maru_sighandler;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_RESTART;
+    sigaction(SIGSEGV, &sa, NULL);
+    sigaction(SIGBUS, &sa, NULL);
+    sigaction(SIGILL, &sa, NULL);
+    sigaction(SIGFPE, &sa, NULL);
+    sigaction(SIGABRT, &sa, NULL);
+    // main thread only
+    sigaction(SIGTERM, &sa, NULL);
+    sigaction(SIGINT, &sa, NULL);
+#endif
+}
index 80cf17041d9b238df67fca4a653cf48f06fe0d81..8ad2bac01aa804723899d48c8771b00057780bf9 100644 (file)
@@ -54,4 +54,5 @@ void maru_atexit(void);
 char *maru_convert_path(char *msg, const char *path);
 void maru_dump_backtrace(void *ptr, int depth);
 
+void maru_register_exception_handler(void);
 #endif /* __EMUL_ERR_TABLE_H__ */
index 37dd298631037fb6ecde7b0a9e95ff4920288f34..d5dc50237b9e3fc18563ecf8e263ee4b2e8f1a4e 100644 (file)
@@ -409,13 +409,20 @@ void qemu_thread_create(QemuThread *thread,
 
     /* Leave signal handling to the iothread.  */
     sigfillset(&set);
+#define DO_NOT_MASK_SYNC_SIGS
+#ifdef DO_NOT_MASK_SYNC_SIGS
+    sigdelset(&set, SIGSEGV);
+    sigdelset(&set, SIGBUS);
+    sigdelset(&set, SIGABRT);
+    sigdelset(&set, SIGFPE);
+    sigdelset(&set, SIGILL);
+#endif
     pthread_sigmask(SIG_SETMASK, &set, &oldset);
     err = pthread_create(&thread->thread, &attr, start_routine, arg);
     if (err)
         error_exit(err, __func__);
 
     pthread_sigmask(SIG_SETMASK, &oldset, NULL);
-
     pthread_attr_destroy(&attr);
 }