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(®s);
- // 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(®s, (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(®s);
+ _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(®s);
+ _exit(-1); // Exit process if not sucessful...
+ }
+
if (signum == SIGSEGV)
clear_stack_protection(®s, 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, ®s, 3,
- ®s, (void*)(size_t)signum, info->si_addr);
+ ®s, (void*)(size_t)signum, fault_addr);
+
// Convert prepared Registers back to OS context
port_thread_regs_to_context((ucontext_t*)context, ®s);
// 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(®s, (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, ®s, 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, ®s, 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, ®s, 1, ®s);
@@ -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)