You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2008/03/28 15:01:21 UTC

svn commit: r642236 - in /harmony/enhanced/drlvm/trunk: make/vm/ vm/port/src/crash_handler/ vm/port/src/signals/include/ vm/port/src/signals/linux/ vm/port/src/signals/win/

Author: gshimansky
Date: Fri Mar 28 07:01:16 2008
New Revision: 642236

URL: http://svn.apache.org/viewvc?rev=642236&view=rev
Log:
Applied patch from HARMONY-5656
[drlvm][port][signals] VM does not show assertion dialog on failed asserts


Modified:
    harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml
    harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp

Modified: harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml (original)
+++ harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml Fri Mar 28 07:01:16 2008
@@ -120,6 +120,7 @@
 
                 <linkerarg value="--version-script=${vm.home}/port/build/ch.exp" if="is.unix"/>
 
+                <syslibset type="shared" libs="user32" if="is.windows"/>
                 <syslibset type="shared" libs="dl,stdc++,pthread,rt" if="is.linux"/>
                 <syslibset type="shared" libs="stdc++,pthread" if="is.freebsd"/>
                 <linkerarg value="--export-dynamic" if="is.freebsd"/>

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/port_crash_handler.cpp Fri Mar 28 07:01:16 2008
@@ -43,7 +43,7 @@
 
 static crash_additional_actions *crash_actions = NULL;
 
-static unsigned crash_output_flags;
+static unsigned crash_output_flags = 0;
 
 static osmutex_t g_mutex;
 
@@ -74,6 +74,15 @@
 
     g_unwind_callback = unwind_callback;
 
+    // Set default flags
+    port_crash_handler_set_flags(
+        PORT_CRASH_DUMP_TO_STDERR |
+        PORT_CRASH_STACK_DUMP |
+        PORT_CRASH_PRINT_COMMAND_LINE |
+        PORT_CRASH_PRINT_ENVIRONMENT |
+        PORT_CRASH_PRINT_MODULES |
+        PORT_CRASH_PRINT_REGISTERS);
+
     return TRUE;
 }
 
@@ -90,12 +99,16 @@
             PORT_CRASH_PRINT_MODULES |
             PORT_CRASH_PRINT_REGISTERS |
             PORT_CRASH_DUMP_PROCESS_CORE);
-
 }
 
 void port_crash_handler_set_flags(unsigned flags)
 {
-    crash_output_flags = flags;
+    unsigned new_flags = flags & port_crash_handler_get_capabilities();
+
+    sig_process_crash_flags_change(new_flags & ~crash_output_flags,
+                                   crash_output_flags & ~new_flags);
+
+    crash_output_flags = new_flags;
 }
 
 unsigned port_crash_handler_get_flags()

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/crash_handler/stack_dump.cpp Fri Mar 28 07:01:16 2008
@@ -117,7 +117,7 @@
 {
     if (!regs)
     {
-        fprintf(stderr, "No stack trace due to registers info absence\n");
+        fprintf(stderr, "\nNo stack trace due to registers info absence\n");
         return;
     }
 

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/include/signals_internal.h Fri Mar 28 07:01:16 2008
@@ -36,10 +36,8 @@
     void*   restart_address;
 #endif /* UNIX */
 
-#ifdef WIN32
-    Boolean assert_dialog;
-#endif
-
+    /* Flag to indicate that debugger should be attached right in OS handler */
+    Boolean debugger;
     /* Flag to produce minidump/core on the second exception catch */
     Boolean   produce_core;
 
@@ -129,13 +127,15 @@
 */
 void port_transfer_to_function(void* fn, Registers* regs, int num, ...);
 
+/* The function called to adjust signals processing upon flags change */
+void sig_process_crash_flags_change(unsigned added, unsigned removed);
 
 
 #define INSTRUMENTATION_BYTE_HLT 0xf4 // HLT instruction
 #define INSTRUMENTATION_BYTE_CLI 0xfa // CLI instruction
 #define INSTRUMENTATION_BYTE_INT3 0xcc // INT 3 instruction
 
-#ifdef WINNT
+#ifdef WIN32
 #define INSTRUMENTATION_BYTE INSTRUMENTATION_BYTE_CLI
 #else
 #define INSTRUMENTATION_BYTE INSTRUMENTATION_BYTE_INT3
@@ -152,6 +152,8 @@
 
 /* Internal exception handler */
 LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception);
+
+void __cdecl port_win_dbg_break(void);
 
 #else /* UNIX */
 

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_common.cpp Fri Mar 28 07:01:16 2008
@@ -23,6 +23,7 @@
 
 #include "open/platform_types.h"
 #include "port_crash_handler.h"
+#include "port_malloc.h"
 #include "stack_dump.h"
 #include "../linux/include/gdb_crash_handler.h"
 #include "signals_internal.h"
@@ -77,18 +78,8 @@
 }
 
 static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
-{ // this exception handler is executed *after* VEH handler returned
+{ // this exception handler is executed *after* OS signal handler returned
     int result;
-    Registers regs = *pregs;
-
-    // Check if SIGSEGV is produced by port_read/write_memory
-    port_tls_data* tlsdata = get_private_tls_data();
-    if (tlsdata && tlsdata->violation_flag)
-    {
-        tlsdata->violation_flag = 0;
-        pregs->set_ip(tlsdata->restart_address);
-        return;
-    }
 
     switch ((int)signum)
     {
@@ -109,6 +100,9 @@
     case SIGQUIT:
         result = port_process_signal(PORT_SIGNAL_QUIT, pregs, fault_addr, FALSE);
         break;
+    case SIGABRT:
+        result = port_process_signal(PORT_SIGNAL_ABORT, NULL, fault_addr, FALSE);
+        break;
     default:
         result = port_process_signal(PORT_SIGNAL_UNKNOWN, pregs, fault_addr, TRUE);
     }
@@ -117,10 +111,18 @@
         return;
 
     // We've got a crash
-    if (result > 0)
-    { // result > 0 - invoke debugger
-        bool result = gdb_crash_handler(&regs);
-        // Continue with exiting process if not sucessful...
+    if (result > 0) // invoke debugger
+    { // Prepare second catch of signal to attach GDB from signal handler
+        port_tls_data* tlsdata = get_private_tls_data();
+        if (!tlsdata)
+        {   // STD_MALLOC can be harmful here
+            tlsdata = (port_tls_data*)STD_MALLOC(sizeof(port_tls_data));
+            memset(tlsdata, 0, sizeof(port_tls_data));
+            set_private_tls_data(tlsdata);
+        }
+
+        tlsdata->debugger = TRUE;
+        return; // To produce signal again
     }
 
     // result < 0 - exit process
@@ -129,6 +131,7 @@
         signal(signum, SIG_DFL); // setup default handler
         return;
     }
+
     // No core needed - simply terminate
     _exit(-1);
 }
@@ -136,16 +139,45 @@
 static void general_signal_handler(int signum, siginfo_t* info, void* context)
 {
     Registers regs;
+
+    if (!context)
+        return;
+
     // Convert OS context to Registers
     port_thread_context_to_regs(&regs, (ucontext_t*)context);
 
+    // Check if SIGSEGV is produced by port_read/write_memory
+    port_tls_data* tlsdata = get_private_tls_data();
+    if (tlsdata && tlsdata->violation_flag)
+    {
+        tlsdata->violation_flag = 0;
+        regs.set_ip(tlsdata->restart_address);
+        return;
+    }
+
+    if (tlsdata && tlsdata->debugger)
+    {
+        bool result = gdb_crash_handler(&regs);
+        _exit(-1); // Exit process if not sucessful...
+    }
+
+    if (signum == SIGABRT && // SIGABRT can't be trown again from c_handler
+        (port_crash_handler_get_flags() & PORT_CRASH_CALL_DEBUGGER) != 0)
+    { // So attaching GDB right here
+        bool result = gdb_crash_handler(&regs);
+        _exit(-1); // Exit process if not sucessful...
+    }
+
     if (signum == SIGSEGV)
         clear_stack_protection(&regs, info->si_addr);
 
     // Prepare registers for transfering control out of signal handler
     void* callback = (void*)&c_handler;
+    void* fault_addr = info ? info->si_addr : NULL;
+
     port_set_longjump_regs(callback, &regs, 3,
-                            &regs, (void*)(size_t)signum, info->si_addr);
+                            &regs, (void*)(size_t)signum, fault_addr);
+
     // Convert prepared Registers back to OS context
     port_thread_regs_to_context((ucontext_t*)context, &regs);
     // Return from signal handler to go to C handler
@@ -218,3 +250,8 @@
     restore_signals();
     return 0;
 } //shutdown_signals
+
+void sig_process_crash_flags_change(unsigned added, unsigned removed)
+{
+// Still empty on Linux
+}

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/linux/signals_ipf.cpp Fri Mar 28 07:01:16 2008
@@ -62,7 +62,7 @@
     // Convert OS context to Registers
     port_thread_context_to_regs(&regs, (ucontext_t*)context);
 
-    void* fault_addr = info->si_addr;
+    void* fault_addr = info ? info->si_addr : NULL;
     int result;
 
     switch ((int)signum)
@@ -84,6 +84,9 @@
     case SIGQUIT:
         result = port_process_signal(PORT_SIGNAL_QUIT, &regs, fault_addr, FALSE);
         break;
+    case SIGABRT:
+        result = port_process_signal(PORT_SIGNAL_ABORT, NULL, fault_addr, FALSE);
+        break;
     default:
         result = port_process_signal(PORT_SIGNAL_UNKNOWN, &regs, fault_addr, TRUE);
     }
@@ -177,6 +180,11 @@
     restore_signals();
     return 0;
 } //shutdown_signals
+
+void sig_process_crash_flags_change(unsigned added, unsigned removed)
+{
+// Still empty on Linux
+}
 
 #if 0
 

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_asm_em64t.asm Fri Mar 28 07:01:16 2008
@@ -25,6 +25,15 @@
 vectored_exception_handler ENDP
 
 
+PUBLIC  port_win_dbg_break
+
+port_win_dbg_break PROC
+;void __declspec(naked) __cdecl port_win_dbg_break()
+    int 3
+    ret
+port_win_dbg_break ENDP
+
+
 ; struct Registers {
 ; uint64 rsp;   ; 00h
 ; uint64 rbp;   ; 08h

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp Fri Mar 28 07:01:16 2008
@@ -17,9 +17,12 @@
 
 
 #include <crtdbg.h>
+#include <process.h>
+#include <signal.h>
 #include "open/platform_types.h"
 #include "open/hythread_ext.h"
 #include "port_malloc.h"
+#include "port_mutex.h"
 
 #include "port_crash_handler.h"
 #include "stack_dump.h"
@@ -37,6 +40,19 @@
 
 port_tls_key_t port_tls_key = TLS_OUT_OF_INDEXES;
 
+typedef void (__cdecl *sigh_t)(int); // Signal handler type
+
+static PVOID veh = NULL;
+static sigh_t prev_sig = (sigh_t)SIG_ERR;
+// Mutex to protect access to the global data
+static osmutex_t g_mutex;
+// The global data protected by the mutex
+static int report_modes[4];
+static _HFILE report_files[3];
+//--------
+static bool asserts_disabled = false;
+
+
 int init_private_tls_data()
 {
     DWORD key = TlsAlloc();
@@ -70,6 +86,10 @@
         result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, iscrash);
         break;
     case STATUS_INTEGER_DIVIDE_BY_ZERO:
+    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+    case EXCEPTION_FLT_OVERFLOW:
+    case EXCEPTION_FLT_UNDERFLOW:
+    case EXCEPTION_INT_OVERFLOW:
         result = port_process_signal(PORT_SIGNAL_ARITHMETIC, pregs, fault_addr, iscrash);
         break;
     case JVMTI_EXCEPTION_STATUS:
@@ -100,12 +120,12 @@
         if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
             tlsdata->produce_core = TRUE;
         if (result > 0)
-            tlsdata->assert_dialog = TRUE;
+            tlsdata->debugger = TRUE;
 
         return; // To produce exception again
     }
 
-    ExitProcess((UINT)-1);
+    _exit(-1);
 }
 
 void prepare_assert_dialog(Registers* regs)
@@ -128,11 +148,11 @@
         {
             tlsdata->produce_core = FALSE;
             create_minidump(nt_exception);
-            if (!tlsdata->assert_dialog)
-                ExitProcess((UINT)-1);
+            if (!tlsdata->debugger)
+                _exit(-1);
         }
 
-        if (tlsdata->assert_dialog)
+        if (tlsdata->debugger)
         {
             // Go to handler to restore CRT/VEH settings and crash once again
             port_set_longjump_regs(&prepare_assert_dialog, &regs, 1, &regs);
@@ -145,11 +165,8 @@
     {
     case STATUS_STACK_OVERFLOW:
     case STATUS_ACCESS_VIOLATION:
-    case STATUS_INTEGER_DIVIDE_BY_ZERO:
     case JVMTI_EXCEPTION_STATUS:
-    case EXCEPTION_DATATYPE_MISALIGNMENT:
-    case EXCEPTION_ILLEGAL_INSTRUCTION:
-    case EXCEPTION_PRIV_INSTRUCTION:
+    case STATUS_INTEGER_DIVIDE_BY_ZERO:
     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
     case EXCEPTION_FLT_OVERFLOW:
     case EXCEPTION_FLT_UNDERFLOW:
@@ -197,8 +214,6 @@
     return FALSE;
 }
 
-static int report_modes[4];
-static _HFILE report_files[3];
 
 static void disable_assert_dialogs()
 {
@@ -226,10 +241,74 @@
 #endif // _DEBUG
 }
 
-static PVOID veh = NULL;
+static void show_debugger_dialog()
+{
+    int result = MessageBox(NULL,
+                    "ABORT handler has requested to call the debugger\n\n"
+                    "Press Retry to attach to the debugger\n"
+                    "Press Cancel to terminate the application",
+                    "Crash Handler",
+                    MB_RETRYCANCEL | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL);
+
+    if (result == IDCANCEL)
+    {
+        _exit(3);
+        return;
+    }
+
+    port_win_dbg_break(); // Call the debugger
+}
+
+static void __cdecl sigabrt_handler(int signum)
+{
+    int result = port_process_signal(PORT_SIGNAL_ABORT, NULL, NULL, FALSE);
+    // There no reason for checking for 0 - abort() will do _exit(3) anyway
+//    if (result == 0)
+//        return;
+
+    shutdown_signals(); // Remove handlers
+
+    if (result > 0) // Assert dialog
+        show_debugger_dialog();
+
+    _exit(3);
+}
+
+static void __cdecl final_sigabrt_handler(int signum)
+{
+    _exit(3);
+}
+
+void sig_process_crash_flags_change(unsigned added, unsigned removed)
+{
+    apr_status_t aprarr = port_mutex_lock(&g_mutex);
+    if (aprarr != APR_SUCCESS)
+        return;
+
+    if ((added & PORT_CRASH_CALL_DEBUGGER) != 0 && asserts_disabled)
+    {
+        restore_assert_dialogs();
+        asserts_disabled = false;
+        signal(SIGABRT, (sigh_t)final_sigabrt_handler);
+    }
+
+    if ((removed & PORT_CRASH_CALL_DEBUGGER) != 0 && !asserts_disabled)
+    {
+        disable_assert_dialogs();
+        asserts_disabled = true;
+        signal(SIGABRT, (sigh_t)sigabrt_handler);
+    }
+
+    port_mutex_unlock(&g_mutex);
+}
 
 int initialize_signals()
 {
+    apr_status_t aprerr = port_mutex_create(&g_mutex, APR_THREAD_MUTEX_NESTED);
+
+    if (aprerr != APR_SUCCESS)
+        return -1;
+
     BOOL ok = SetConsoleCtrlHandler((PHANDLER_ROUTINE)ctrl_handler, TRUE);
 
     if (!ok)
@@ -241,15 +320,28 @@
     if (!veh)
         return -1;
 
+    prev_sig = signal(SIGABRT, (sigh_t)sigabrt_handler);
+
+    if (prev_sig == SIG_ERR)
+        return -1;
+
     disable_assert_dialogs();
+    asserts_disabled = true;
 
     return 0;
 }
 
 int shutdown_signals()
 {
-    ULONG res;
-    res = RemoveVectoredExceptionHandler(veh);
+    if (asserts_disabled)
+    {
+        restore_assert_dialogs();
+        asserts_disabled = false;
+    }
+
+    signal(SIGABRT, prev_sig);
+
+    ULONG res = RemoveVectoredExceptionHandler(veh);
 
     if (!res)
         return -1;
@@ -259,7 +351,6 @@
     if (!ok)
         return -1;
 
-    restore_assert_dialogs();
-
+    port_mutex_destroy(&g_mutex);
     return 0;
 } //shutdown_signals

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp?rev=642236&r1=642235&r2=642236&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp Fri Mar 28 07:01:16 2008
@@ -36,6 +36,11 @@
     }
 }
 
+void __declspec(naked) __cdecl port_win_dbg_break()
+{
+__asm { int 3 }
+}
+
 
 extern "C" void port_longjump_stub(void);
 #define DIR_FLAG ((uint32)0x00000400)