You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ib...@apache.org on 2008/05/26 02:33:07 UTC
svn commit: r660062 [1/2] - in /harmony/enhanced/drlvm/trunk: make/vm/
vm/include/open/ vm/port/build/ vm/port/include/ vm/port/src/crash_handler/
vm/port/src/memaccess/linux/ vm/port/src/signals/
vm/port/src/signals/include/ vm/port/src/signals/linux/...
Author: iberezhn
Date: Sun May 25 17:33:06 2008
New Revision: 660062
URL: http://svn.apache.org/viewvc?rev=660062&view=rev
Log:
Applied patch from HARMONY-5617
[drlvm] On Linux crash handler may crash itself when handling SOE
condition
The patch moves platform-dependent threading from TM to Portlib, and
platform-dependent signals processing from VMCore to Portlib.
Added:
harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/
harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h (with props)
harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c (with props)
harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c (with props)
harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_find.c (with props)
harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/port_thread_tls_os.c (with props)
Removed:
harmony/enhanced/drlvm/trunk/vm/thread/src/linux/os_thread.c
harmony/enhanced/drlvm/trunk/vm/thread/src/win/os_thread.c
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/include/signals_common.h
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ipf.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32_em64t/nt_exception_filter_common.cpp
Modified:
harmony/enhanced/drlvm/trunk/make/vm/hythr.xml
harmony/enhanced/drlvm/trunk/make/vm/port.xml
harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml
harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h
harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp
harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h
harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h
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/memaccess/linux/memaccess.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/port_signals.cpp
harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_common.cpp
harmony/enhanced/drlvm/trunk/vm/port/src/signals/win/signals_ia32.cpp
harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/thread_os.c
harmony/enhanced/drlvm/trunk/vm/port/src/thread/win/thread_os.c
harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.def
harmony/enhanced/drlvm/trunk/vm/thread/src/hythr.exp
harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_attrs.c
harmony/enhanced/drlvm/trunk/vm/thread/src/thread_native_basic.c
harmony/enhanced/drlvm/trunk/vm/thread/src/thread_private.h
harmony/enhanced/drlvm/trunk/vm/vmcore/include/exceptions.h
harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_generic.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/thread/thread_java_basic.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/signals.cpp
Modified: harmony/enhanced/drlvm/trunk/make/vm/hythr.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/make/vm/hythr.xml?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/make/vm/hythr.xml (original)
+++ harmony/enhanced/drlvm/trunk/make/vm/hythr.xml Sun May 25 17:33:06 2008
@@ -47,8 +47,8 @@
<linkerarg value="/DEF:${vm.home}/thread/src/hythr.def" if="is.windows"/>
- <syslibset libs="stdc++,rt,pthread" if="is.linux"/>
- <syslibset libs="stdc++,pthread" if="is.freebsd"/>
+ <syslibset type="shared" libs="stdc++,rt,pthread" if="is.linux"/>
+ <syslibset type="shared" libs="stdc++,pthread" if="is.freebsd"/>
<linkerarg value="-Wl,-init" if="is.unix"/>
<linkerarg value="-Wl,hythread_library_init" if="is.unix"/>
<linkerarg value="-Wl,--version-script,${vm.home}/thread/src/hythr.exp" if="is.unix"/>
Modified: harmony/enhanced/drlvm/trunk/make/vm/port.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/make/vm/port.xml?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/make/vm/port.xml (original)
+++ harmony/enhanced/drlvm/trunk/make/vm/port.xml Sun May 25 17:33:06 2008
@@ -29,6 +29,7 @@
<dirset dir="${vm.home}">
<include name="include" />
<include name="port/include" />
+ <include name="port/src/thread/include" />
</dirset>
<pathelement location="${drlvm.include.dir}"/>
<pathelement location="${hy.hdk}/include" />
@@ -49,10 +50,12 @@
<include name="vmem/win/*.c" if="is.windows"/>
<include name="file_io/*.c"/>
+ <include name="thread/linux/port_thread_tls_find.c" if="is.unix"/>
<include name="thread/linux/thread_os.c" if="is.unix"/>
<include name="thread/linux/*ia32.c" if="is.unix.x86"/>
<include name="thread/linux/*em64t.c" if="is.unix.x86_64"/>
<include name="thread/linux/*ipf.c" if="is.unix.ia64"/>
+ <include name="thread/win/port_thread_tls_find.c" if="is.windows"/>
<include name="thread/win/thread_os.c" if="is.windows"/>
<include name="thread/win/*ia32.c" if="is.windows.x86"/>
<include name="thread/win/*em64t.c" if="is.windows.x86_64"/>
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=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml (original)
+++ harmony/enhanced/drlvm/trunk/make/vm/port_ch.xml Sun May 25 17:33:06 2008
@@ -30,6 +30,7 @@
<include name="include" />
<include name="port/include" />
<include name="port/src/signals/include" />
+ <include name="port/src/thread/include" />
<include name="port/src/crash_handler/include" />
<include name="port/src/encoder/ia32_em64t" unless="is.ia64"/>
</dirset>
@@ -42,14 +43,20 @@
<include name="modules/linux/*.c" if="is.unix"/>
<include name="modules/win/*.c" if="is.windows"/>
+ <include name="thread/linux/thread_os.c" if="is.unix"/>
+ <include name="thread/linux/port_thread_tls_os.c" if="is.unix"/>
<include name="thread/linux/*ia32.c" if="is.unix.x86"/>
<include name="thread/linux/*em64t.c" if="is.unix.x86_64"/>
<include name="thread/linux/*ipf.c" if="is.unix.ia64"/>
+ <include name="thread/win/thread_os.c" if="is.windows"/>
+ <include name="thread/win/port_thread_tls_os.c" if="is.windows"/>
<include name="thread/win/*ia32.c" if="is.windows.x86"/>
<include name="thread/win/*em64t.c" if="is.windows.x86_64"/>
<include name="misc/linux/execname.c" if="is.unix"/>
<include name="misc/win/execname.c" if="is.windows"/>
+ <!-- port_atomic_casptr is inlined on all platforms except ia64 -->
+ <include name="atomic/linux_ipf/*.c" if="is.unix.ia64"/>
</patternset>
<patternset id="ch.src.cpp">
Modified: harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/include/open/hythread_ext.h Sun May 25 17:33:06 2008
@@ -346,11 +346,6 @@
char need_to_free;
/**
- * Size of thread's stack, set on creation
- */
- UDATA stacksize;
-
- /**
* Flag of interruption
*/
U_32 interrupted;
@@ -445,7 +440,6 @@
UDATA VMCALL hythread_tls_get_offset(hythread_tls_key_t key);
UDATA VMCALL hythread_tls_get_request_offset();
UDATA VMCALL hythread_get_thread_times(hythread_t thread, int64* pkernel, int64* puser);
-UDATA hythread_get_thread_stacksize(hythread_t thread);
UDATA VMCALL hythread_uses_fast_tls(void);
IDATA VMCALL hythread_get_hythread_offset_in_tls(void);
IDATA VMCALL hythread_get_struct_size();
Modified: harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/build/ch.exp Sun May 25 17:33:06 2008
@@ -16,6 +16,7 @@
port_init_unwind_context;
port_clean_unwind_context;
port_unwind_frame;
+ port_init_shared_data;
#
local : *;
};
Modified: harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/include/port_general.h Sun May 25 17:33:06 2008
@@ -58,5 +58,15 @@
#endif /* __cplusplus */
+#ifdef _IA32_
+#ifdef WIN32
+#define PORT_CDECL __cdecl
+#else /* !WIN32 */
+#define PORT_CDECL __attribute__ ((cdecl))
+#endif /* WIN32 */
+#else /* _IA32_ */
+#define PORT_CDECL
+#endif /* _IA32_ */
+
#endif /* _PORT_GENERAL_H_ */
Modified: harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/include/port_thread.h Sun May 25 17:33:06 2008
@@ -50,6 +50,7 @@
#endif /* LINUX || FREEBSD */
+
/* To skip platform_types.h inclusion */
typedef struct Registers Registers;
@@ -71,18 +72,251 @@
#endif
}
-void port_thread_yield_other(osthread_t thread);
+/**
+ * The type of pointer to thread start function
+ * Function receives single argument - user-defined pointer
+ */
+typedef int (PORT_CDECL *port_threadfunc_t)(void*);
+
+/**
+ * Creates new thread.
+ *
+ * @param[out] handle on success, thread handle is stored in memory pointed by handle
+ * @param stacksize size of stack to be allocated for a new thread
+ * @param priority priority of a new thread
+ * @param func function to be started on a new thread
+ * @param data value to be passed to a function started on a new thread
+ *
+ * @return 0 on success, system error otherwise.
+ */
+int port_thread_create(osthread_t* phandle, size_t stacksize, int priority,
+ port_threadfunc_t func, void *data);
+
+/**
+ * Attaches current thread to the porting library.
+ *
+ * This includes setting guard page in thread's stack memory and setting
+ * alternative stack for stack overflow processing.
+ * This function should be called for any thread which can produce expected
+ * hardware signals/exceptions, to guarantee proper signals processing.
+ *
+ * @return 0 on success, system error otherwise.
+ *
+ * @sa port_thread_detach()
+ */
+int port_thread_attach();
+
+/**
+ * Detaches current thread from the porting library.
+ * This includes restoring thread's stack settings.
+ *
+ * @return 0 on success, system error otherwise.
+ *
+ * @sa port_thread_attach()
+ */
+int port_thread_detach();
+
+/**
+ * Restores guard page after stack overflow processing, when
+ * <code>port_thread_postpone_guard_page()</code> function was used
+ * to postpone authomatic gurd page restoring.
+ *
+ * @return 0 on success, system error otherwise.
+ *
+ * @sa port_thread_postpone_guard_page()
+ * @sa port_thread_clear_guard_page()
+ */
+int port_thread_restore_guard_page();
+
+/**
+ * Clears guard page in thread's stack on demand.
+ * Guard page is cleared automatically for stack overflow processing; this
+ * function allows clearing it when needed for other purposes.
+ * Guard page can be restored with
+ * <code>port_thread_postpone_guard_page()</code> function.
+ *
+ * @return 0 on success, system error otherwise.
+ *
+ * @sa port_thread_restore_guard_page()
+ */
+int port_thread_clear_guard_page();
+
+/**
+ * Postpones automatic guard page restoring after stack overflow processing.
+ *
+ * This function can be used inside of STACK_OVERFLOW signal callback to
+ * disable automatic guard poge restoring. This is useful when the program
+ * expects to consume some more stack before unwinding to SO handler.
+ *
+ * @sa port_thread_restore_guard_page()
+ */
+void port_thread_postpone_guard_page();
+
+
+/**
+ * Returns stack bottom address for the current thread.
+ *
+ * @return NULL on error
+ */
+void* port_thread_get_stack_address();
+
+
+/**
+ * Returns total thread's stack size for the current thread.
+ *
+ * @return 0 on error
+ */
+size_t port_thread_get_stack_size();
+
+
+/**
+ * Returns effective stack size for the current thread.
+ * Effective stack size is an area from stack bottom to guard page.
+ *
+ * Return value depends thread's state. When the thread is not in signal,
+ * return value is a total stack size excluding system page, i.e.
+ * (port_thread_get_stack_size() - <guard page size>). When processing a signal,
+ * return value is the same when guard page is cleared, and is a size of area
+ * from stack bottom to Port's guard page otherwise.
+ *
+ * @return 0 on error
+ */
+size_t port_thread_get_effective_stack_size();
+
+
+/**
+ * Adjusts priority of the running thread.
+ *
+ * @param thread handle of thread
+ * @param priority new priority value
+ *
+ * @return 0 on success, system error otherwise
+ */
+int port_thread_set_priority(osthread_t thread, int priority);
+
+/**
+ * Returns os handle of the current thread.
+ *
+ * @return current thread handle on success, NULL on error
+ *
+ * @note The handle returned need to be freed by port_thread_free_handle()
+ * @sa port_thread_free_handle()
+ */
+osthread_t port_thread_current();
+
+/**
+ * Frees thread handle returned by port_thread_current()
+ *
+ * @param os_thread thread handle
+ *
+ * @sa port_thread_current()
+ */
+int port_thread_free_handle(osthread_t os_thread);
+
+/**
+ * Joins the os thread.
+ *
+ * @param os_thread thread handle
+ *
+ * @return 0 on success, systerm error otherwise
+ */
+int port_thread_join(osthread_t os_thread);
+
+/**
+ * Terminates the os thread.
+ *
+ * @param os_thread thread to terminate
+ */
int port_thread_cancel(osthread_t os_thread);
+/**
+ * Causes the current thread to stop execution.
+ *
+ * @param status return status of a thread
+ */
+void port_thread_exit(int status);
+
+/**
+ * Queries amount of user and kernel times consumed by the thread,
+ * in nanoseconds.
+ *
+ * @param os_thread thread handle
+ * @param[out] pkernel a pointer to a variable to store kernel time to
+ * @param[out] puser a pointer to a variable to store user time to
+ *
+ * @return 0 on success, system error otherwise
+ */
+int port_get_thread_times(osthread_t os_thread, int64* pkernel, int64* puser);
+
+/**
+ * Causes the other thread to have a memory barrier by suspending
+ * and resuming it.
+ *
+ * @param thread thread handle
+ */
+void port_thread_yield_other(osthread_t thread);
+/**
+ * Suspend given thread
+ *
+ * @param thread The thread to suspend
+ */
int port_thread_suspend(osthread_t thread);
+
+/**
+ * Resume given thread
+ *
+ * @param thread The thread to resume
+ */
int port_thread_resume(osthread_t thread);
+
+/**
+ * Returnd suspend count for the given thread
+ *
+ * @param thread The thread to check
+ *
+ * @return suspend count of the thread, -1 if error
+ */
int port_thread_get_suspend_count(osthread_t thread);
+/**
+ * Get context for given thread
+ *
+ * @param thread The thread to process
+ * @param context Pointer to platform-dependent context structure
+ *
+ * @return 0 if successful, -1 otherwise
+ *
+ * @note The thread must be suspended
+ */
int port_thread_get_context(osthread_t thread, thread_context_t* pcontext);
+
+/**
+ * Set context for given thread
+ *
+ * @param thread The thread to process
+ * @param context Pointer to platform-dependent context structure
+ *
+ * @return 0 if successful, -1 otherwise
+ *
+ * @note The thread must be suspended
+ */
int port_thread_set_context(osthread_t thread, thread_context_t* pcontext);
+/**
+ * Translates platform-dependent thread context to Registers structure
+ *
+ * @param regs Pointer to Registers structure
+ * @param context Pointer to platform-dependent context structure
+ */
void port_thread_context_to_regs(Registers* regs, thread_context_t* context);
+
+/**
+ * Translates Registers structure to platform-dependent thread context
+ *
+ * @param context Pointer to platform-dependent context structure
+ * @param regs Pointer to Registers structure
+ */
void port_thread_regs_to_context(thread_context_t* context, Registers* regs);
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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -58,9 +58,6 @@
if (port_mutex_create(&g_mutex, APR_THREAD_MUTEX_NESTED) != APR_SUCCESS)
return FALSE;
- if (init_private_tls_data() != 0)
- return FALSE;
-
for (unsigned iii = 0; iii < count; iii++)
{
assert(registrations[iii].signum >= PORT_SIGNAL_MIN);
@@ -136,9 +133,6 @@
if (shutdown_signals() != 0)
return FALSE;
- if (free_private_tls_data() != 0)
- return FALSE;
-
for (crash_additional_actions *a = crash_actions; NULL != a;)
{
crash_additional_actions *next = a->next;
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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -58,8 +58,12 @@
"%s\n", // No signature no sourcefile
};
-static void sd_print_vm_line(FILE* file, int count, port_stack_frame_info* fi)
+static void sd_print_vm_line(FILE* file, int count, Registers* regs, port_stack_frame_info* fi)
{
+ static char pi_blanks[2*sizeof(void*) + 3];
+ static void* pi_blanks_set_res = memset(pi_blanks, ' ', sizeof(pi_blanks));
+ static char pi_blanks_zero_res = (pi_blanks[sizeof(pi_blanks) - 1] = 0);
+
if (!fi->method_name)
return;
@@ -68,6 +72,11 @@
else
fprintf(file, " "); // additional VM info - indent
+ if (regs)
+ fprintf(file, "0x%"W_PI_FMT" ", regs->get_ip());
+ else
+ fprintf(file, "%s ", pi_blanks); // additional VM info - indent
+
const void* args[5] = {fi->method_class_name, fi->method_name,
fi->method_signature, fi->source_file_name,
(const void*)(size_t)fi->source_line_number};
@@ -93,13 +102,13 @@
}
-static void sd_print_c_line(FILE* file, int count, CFunInfo* cfi)
+static void sd_print_c_line(FILE* file, int count, Registers* regs, CFunInfo* cfi)
{
if (!cfi->name)
return;
- fprintf(file, "%3d: %s (%s:%d)\n",
- count, cfi->name,
+ fprintf(file, "%3d: 0x%"W_PI_FMT" %s (%s:%d)\n",
+ count, regs->get_ip(), cfi->name,
cfi->filename ? cfi->filename : "??",
cfi->line);
}
@@ -124,6 +133,7 @@
fprintf(stderr, "\nStack trace:\n");
Registers locregs = *regs;
+ Registers tmpregs = locregs;
UnwindContext uwcontext;
bool hasnative = false;
@@ -155,10 +165,11 @@
// Unwinding with VM callback
if (unwind && uwresult == 0)
{
- sd_print_vm_line(stderr, framenum++, &uwinfo);
+ sd_print_vm_line(stderr, framenum++, &tmpregs, &uwinfo);
// Cleanup frame info except 'iteration_state'
memset(&uwinfo, 0, offsetof(port_stack_frame_info, iteration_state));
// Try unwinding by the callback for next iteration
+ tmpregs = locregs;
uwresult = unwind(&locregs, &uwinfo);
continue;
}
@@ -167,11 +178,11 @@
CFunInfo cfi = {0};
native_module_t* module = port_find_module(uwcontext.modules, locregs.get_ip());
sd_get_c_method_info(&cfi, module, locregs.get_ip());
- sd_print_c_line(stderr, framenum++, &cfi);
+ sd_print_c_line(stderr, framenum++, &locregs, &cfi);
if (unwind && uwresult < 0 && uwinfo.method_name)
{ // VM has not unwound but has provided additional frame info
- sd_print_vm_line(stderr, -1, &uwinfo); // Print as additional info
+ sd_print_vm_line(stderr, -1, NULL, &uwinfo); // Print as additional info
}
if (!hasnative) // Native unwinding is not initialized
@@ -186,6 +197,7 @@
// Cleanup frame info except 'iteration_state'
memset(&uwinfo, 0, offsetof(port_stack_frame_info, iteration_state));
// Try unwinding by the callback for next iteration
+ tmpregs = locregs;
uwresult = unwind(&locregs, &uwinfo);
}
Modified: harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/memaccess/linux/memaccess.cpp Sun May 25 17:33:06 2008
@@ -24,9 +24,11 @@
#include "port_general.h"
#include "port_barriers.h"
+#include "port_malloc.h"
#include "signals_internal.h"
#include "port_memaccess.h"
+#include "port_thread_internal.h"
extern "C" void port_memcpy_asm(void* dst, const void* src, size_t size,
@@ -35,22 +37,28 @@
static int memcpy_internal(void* dst, const void* src, size_t size, int from)
{
- port_tls_data tlsdata;
+ int res;
+ port_tls_data_t* tlsdata = get_private_tls_data();
- if (!get_private_tls_data())
+ if (!tlsdata)
{
- if (set_private_tls_data(&tlsdata) != 0)
- return -1;
+ tlsdata = (port_tls_data_t*)STD_ALLOCA(sizeof(port_tls_data_t));
+
+ res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);
+
+ if (res != 0)
+ return res;
}
- tlsdata.violation_flag = 1;
+ tlsdata->violation_flag = 1;
void* memcpyaddr = (void*)&memcpy;
- port_memcpy_asm(dst, src, size, &tlsdata.restart_address, memcpyaddr);
+ port_memcpy_asm(dst, src, size, &tlsdata->restart_address, memcpyaddr);
- if (tlsdata.violation_flag == 1)
+ if (tlsdata->violation_flag == 1)
{
- pthread_setspecific(port_tls_key, NULL);
+ tlsdata->violation_flag = 0;
+ port_thread_detach_temporary();
return 0;
}
@@ -76,14 +84,20 @@
}
if (result != 0)
+ {
+ tlsdata->violation_flag = 0;
+ port_thread_detach_temporary();
return -1;
+ }
- tlsdata.violation_flag = 1;
+ tlsdata->violation_flag = 1;
- port_memcpy_asm(dst, src, size, &tlsdata.restart_address, memcpyaddr);
+ port_memcpy_asm(dst, src, size, &tlsdata->restart_address, memcpyaddr);
- pthread_setspecific(port_tls_key, NULL);
- return (tlsdata.violation_flag == 1) ? 0 : -1;
+ res = (tlsdata->violation_flag == 1) ? 0 : -1;
+ tlsdata->violation_flag = 0;
+ port_thread_detach_temporary();
+ return res;
}
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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -19,67 +19,14 @@
#define _SIGNALS_INTERNAL_H_
#include "port_general.h"
-#include "port_thread.h"
#include "open/platform_types.h"
#include "open/hythread_ext.h" /* For windows.h */
-
-/* Thread-specific structure */
-typedef struct
-{
- /* Previous crash handling stage to restart crash processing */
- int crash_stage;
-
-#ifndef WIN32 /* UNIX */
- /* Flag and restart address for memory access violation detection */
- int violation_flag;
- void* restart_address;
-#endif /* UNIX */
-
- /* 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;
-
-} port_tls_data;
-
-
-#ifdef WIN32
-typedef DWORD port_tls_key_t;
-#else
-typedef pthread_key_t port_tls_key_t;
-#endif
-
-
#ifdef __cplusplus
extern "C" {
#endif
-extern port_tls_key_t port_tls_key;
-
-int init_private_tls_data();
-int free_private_tls_data();
-
-PORT_INLINE port_tls_data* get_private_tls_data()
-{
-#ifdef WIN32
- return (port_tls_data*)TlsGetValue(port_tls_key);
-#else
- return (port_tls_data*)pthread_getspecific(port_tls_key);
-#endif
-}
-
-PORT_INLINE int set_private_tls_data(port_tls_data* data)
-{
-#ifdef WIN32
- return TlsSetValue(port_tls_key, data) ? 0 : -1;
-#else
- return pthread_setspecific(port_tls_key, data);
-#endif
-}
-
-
/* Transfer control to specified register context */
void port_transfer_to_regs(Registers* regs);
@@ -153,7 +100,7 @@
/* Internal exception handler */
LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception);
-void __cdecl port_win_dbg_break(void);
+void PORT_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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -27,64 +27,45 @@
#include "stack_dump.h"
#include "../linux/include/gdb_crash_handler.h"
#include "signals_internal.h"
+#include "port_thread_internal.h"
-port_tls_key_t port_tls_key;
+#define FLAG_CORE ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+#define FLAG_DBG ((port_crash_handler_get_flags() & PORT_CRASH_CALL_DEBUGGER) != 0)
-int init_private_tls_data()
-{
- return (pthread_key_create(&port_tls_key, NULL) == 0) ? 0 : -1;
-}
-
-int free_private_tls_data()
-{
- return (pthread_key_delete(port_tls_key) == 0) ? 0 : -1;
-}
-
-// Because application can set up some protected area in stack region,
-// we need to re-enable access to this area because we need to operate
-// with the original stack of the thread
-// Application should take care of restoring this protected area after
-// signal processing
-// FIXME This is workaround only; it also can break crash processing for SIGSEGV
-// Ideally all the functionality on guard pages should be in Port.
-// Unfortunately, it can involve thread creation in Port, additional
-// thread wrapper, and moving general TLS operations to Port, so
-// it's postponed
-static void clear_stack_protection(Registers* regs, void* fault_addr)
+bool is_stack_overflow(port_tls_data_t* tlsdata, void* fault_addr)
{
- if (!fault_addr) // is not SO
- return;
-
- size_t fault = (size_t)fault_addr;
- size_t sp = (size_t)regs->get_sp();
- size_t diff = (fault > sp) ? (fault - sp) : (sp - fault);
- size_t page_size = (size_t)sysconf(_SC_PAGE_SIZE);
-
- if (diff > page_size)
- return; // Most probably is not SO
-
- size_t start = sp & ~(page_size - 1);
- size_t size = page_size;
+ if (!tlsdata || !fault_addr)
+ return false;
- if (sp - start < 0x400)
+ if (tlsdata->guard_page_addr)
{
- start -= page_size;
- size += page_size;
+ return (fault_addr >= tlsdata->guard_page_addr &&
+ (size_t)fault_addr < (size_t)tlsdata->guard_page_addr
+ + tlsdata->guard_page_size);
}
- int res = mprotect((void*)start, size, PROT_READ | PROT_WRITE);
+ size_t stack_top =
+ (size_t)tlsdata->stack_addr - tlsdata->stack_size + tlsdata->guard_page_size;
+
+ // Determine that fault is beyond stack top
+ return ((size_t)fault_addr < stack_top &&
+ (size_t)fault_addr > stack_top - tlsdata->stack_size);
}
static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
{ // this exception handler is executed *after* OS signal handler returned
int result;
+ port_tls_data_t* tlsdata = get_private_tls_data();
switch ((int)signum)
{
case SIGSEGV:
- result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, FALSE);
+ if (tlsdata->restore_guard_page)
+ result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, pregs, fault_addr, FALSE);
+ else
+ result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, FALSE);
break;
case SIGFPE:
result = port_process_signal(PORT_SIGNAL_ARITHMETIC, pregs, fault_addr, FALSE);
@@ -108,25 +89,35 @@
}
if (result == 0)
+ {
+ // Restore guard page if needed
+ if (tlsdata->restore_guard_page)
+ {
+ port_thread_restore_guard_page();
+ tlsdata->restore_guard_page = FALSE;
+
+ if (port_thread_detach_temporary() == 0)
+ STD_FREE(tlsdata);
+ }
return;
+ }
// We've got a crash
+ if (signum == SIGSEGV)
+ {
+ port_thread_restore_guard_page(); // To catch SO again
+ tlsdata->restore_guard_page = FALSE;
+ }
+
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);
- }
-
+ //assert(tlsdata); // Should be attached - provided by general_signal_handler
tlsdata->debugger = TRUE;
return; // To produce signal again
}
// result < 0 - exit process
- if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+ if (FLAG_CORE)
{ // Return to the same place to produce the same crash and generate core
signal(signum, SIG_DFL); // setup default handler
return;
@@ -145,9 +136,10 @@
// Convert OS context to Registers
port_thread_context_to_regs(®s, (ucontext_t*)context);
+ void* fault_addr = info ? info->si_addr : NULL;
// Check if SIGSEGV is produced by port_read/write_memory
- port_tls_data* tlsdata = get_private_tls_data();
+ port_tls_data_t* tlsdata = get_private_tls_data();
if (tlsdata && tlsdata->violation_flag)
{
tlsdata->violation_flag = 0;
@@ -155,25 +147,87 @@
return;
}
- if (tlsdata && tlsdata->debugger)
+ if (!tlsdata) // Tread is not attached - attach thread temporarily
+ {
+ int res;
+ tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));
+
+ if (tlsdata) // Try to attach the thread
+ res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);
+
+ if (!tlsdata || res != 0)
+ { // Can't process correctly; perform default actions
+ if (FLAG_DBG)
+ {
+ bool result = gdb_crash_handler(®s);
+ _exit(-1); // Exit process if not sucessful...
+ }
+
+ if (FLAG_CORE &&
+ signum != SIGABRT) // SIGABRT can't be rethrown
+ {
+ signal(signum, SIG_DFL); // setup default handler
+ return;
+ }
+
+ _exit(-1);
+ }
+
+ // SIGSEGV can represent SO which can't be processed out of signal handler
+ if (signum == SIGSEGV && // This can occur only when a user set an alternative stack
+ is_stack_overflow(tlsdata, fault_addr))
+ {
+ int result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, ®s, fault_addr, FALSE);
+
+ if (result == 0)
+ {
+ if (port_thread_detach_temporary() == 0)
+ STD_FREE(tlsdata);
+ return;
+ }
+
+ if (result > 0)
+ tlsdata->debugger = TRUE;
+ else
+ {
+ if (FLAG_CORE)
+ { // Rethrow crash to generate core
+ signal(signum, SIG_DFL); // setup default handler
+ return;
+ }
+ _exit(-1);
+ }
+ }
+ }
+
+ if (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)
+ FLAG_DBG)
{ // 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);
+ if (signum == SIGSEGV &&
+ is_stack_overflow(tlsdata, fault_addr))
+ {
+ // Second SO while previous SO is not processed yet - is GPF
+ if (tlsdata->restore_guard_page)
+ tlsdata->restore_guard_page = FALSE;
+ else
+ { // To process signal on protected stack area
+ port_thread_clear_guard_page();
+ tlsdata->restore_guard_page = TRUE;
+ }
+ }
// 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, fault_addr);
@@ -223,7 +277,8 @@
for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++)
{
- if (!sd_is_handler_registered(signals_used[i].port_sig))
+ if (!sd_is_handler_registered(signals_used[i].port_sig) &&
+ signals_used[i].signal != SIGSEGV) // Sigsegv is needed for port_memaccess
continue;
sigemptyset(&sa.sa_mask);
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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -21,37 +21,53 @@
#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"
+#include "port_thread_internal.h"
-port_tls_key_t port_tls_key;
+#define FLAG_CORE ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+#define FLAG_DBG ((port_crash_handler_get_flags() & PORT_CRASH_CALL_DEBUGGER) != 0)
-int init_private_tls_data()
-{
- return (pthread_key_create(&port_tls_key, NULL) == 0) ? 0 : -1;
+/* Out-of-signal-handler signal processing is not implemented for IPF
+
+static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
+{ // this exception handler is executed *after* VEH handler returned
}
+*/
-int free_private_tls_data()
+bool is_stack_overflow(port_tls_data_t* tlsdata, void* fault_addr)
{
- return (pthread_key_delete(port_tls_key) == 0) ? 0 : -1;
-}
+ if (!tlsdata || !fault_addr)
+ return false;
+ if (tlsdata->guard_page_addr)
+ {
+ return (fault_addr >= tlsdata->guard_page_addr &&
+ (size_t)fault_addr < (size_t)tlsdata->guard_page_addr
+ + tlsdata->guard_page_size);
+ }
-/* Out-of-signal-handler signal processing is not implemented for IPF
+ size_t stack_top =
+ (size_t)tlsdata->stack_addr - tlsdata->stack_size + tlsdata->guard_page_size;
-static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
-{ // this exception handler is executed *after* VEH handler returned
+ // Determine that fault is beyond stack top
+ return ((size_t)fault_addr < stack_top &&
+ (size_t)fault_addr > stack_top - tlsdata->stack_size);
}
-*/
static void general_signal_handler(int signum, siginfo_t* info, void* context)
{
Registers regs;
+ port_tls_data_t* tlsdata = get_private_tls_data();
+
+ if (!context)
+ return;
+
/* Not implemented
// 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;
@@ -63,6 +79,60 @@
port_thread_context_to_regs(®s, (ucontext_t*)context);
void* fault_addr = info ? info->si_addr : NULL;
+
+ if (!tlsdata) // Tread is not attached - attach thread temporarily
+ {
+ int res;
+ tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));
+
+ if (tlsdata) // Try to attach the thread
+ res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);
+
+ if (!tlsdata || res != 0)
+ { // Can't process correctly; perform default actions
+ if (FLAG_DBG)
+ {
+ bool result = gdb_crash_handler(®s);
+ _exit(-1); // Exit process if not sucessful...
+ }
+
+ if (FLAG_CORE &&
+ signum != SIGABRT) // SIGABRT can't be rethrown
+ {
+ signal(signum, SIG_DFL); // setup default handler
+ return;
+ }
+
+ _exit(-1);
+ }
+
+ // SIGSEGV can represent SO which can't be processed out of signal handler
+ if (signum == SIGSEGV && // This can occur only when a user set an alternative stack
+ is_stack_overflow(tlsdata, fault_addr))
+ {
+ int result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, ®s, fault_addr, FALSE);
+
+ if (result == 0)
+ {
+ if (port_thread_detach_temporary() == 0)
+ STD_FREE(tlsdata);
+ return;
+ }
+
+ if (result > 0)
+ tlsdata->debugger = TRUE;
+ else
+ {
+ if (FLAG_CORE)
+ { // Rethrow crash to generate core
+ signal(signum, SIG_DFL); // setup default handler
+ return;
+ }
+ _exit(-1);
+ }
+ }
+ }
+
int result;
switch ((int)signum)
@@ -91,21 +161,26 @@
result = port_process_signal(PORT_SIGNAL_UNKNOWN, ®s, fault_addr, TRUE);
}
- if (result == 0)
+ // Convert Registers back to OS context
+ port_thread_regs_to_context((ucontext_t*)context, ®s);
+
+ if (result == 0) // Signal was processed - continue execution
+ {
+ if (port_thread_detach_temporary() == 0)
+ STD_FREE(tlsdata);
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...
+ // Continue with making core or exiting process if not successful...
}
- // Convert Registers back to OS context
- port_thread_regs_to_context((ucontext_t*)context, ®s);
-
// result < 0 - exit process
- if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+ if (FLAG_CORE &&
+ signum != SIGABRT) // SIGABRT can't be rethrown
{ // Return to the same place to produce the same crash and generate core
signal(signum, SIG_DFL); // setup default handler
return;
Modified: harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp?rev=660062&r1=660061&r2=660062&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/signals/port_signals.cpp Sun May 25 17:33:06 2008
@@ -26,12 +26,20 @@
if (!addr || !prev)
return -1;
+ unsigned char buf;
unsigned char instr = INSTRUMENTATION_BYTE;
- if (port_read_memory(addr, 1, prev) != 0)
+ int err = port_read_memory(addr, 1, &buf);
+ if (err != 0) return err;
+
+ if (buf == instr)
return -1;
- return port_write_memory(addr, 1, &instr);
+ err = port_write_memory(addr, 1, &instr);
+ if (err != 0) return err;
+
+ *prev = buf;
+ return 0;
}
int port_clear_breakpoint(void* addr, unsigned char prev)
@@ -39,6 +47,15 @@
if (!addr)
return -1;
+ unsigned char buf;
+ unsigned char instr = INSTRUMENTATION_BYTE;
+
+ int err = port_read_memory(addr, 1, &buf);
+ if (err != 0) return err;
+
+ if (buf != instr)
+ return -1;
+
return port_write_memory(addr, 1, &prev);
}
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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -27,6 +27,7 @@
#include "port_crash_handler.h"
#include "stack_dump.h"
#include "signals_internal.h"
+#include "port_thread_internal.h"
#if INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_INT3
@@ -37,10 +38,11 @@
#error Unknown value of INSTRUMENTATION_BYTE
#endif
+#define FLAG_CORE ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+#define FLAG_DBG ((port_crash_handler_get_flags() & PORT_CRASH_CALL_DEBUGGER) != 0)
-port_tls_key_t port_tls_key = TLS_OUT_OF_INDEXES;
-typedef void (__cdecl *sigh_t)(int); // Signal handler type
+typedef void (PORT_CDECL *sigh_t)(int); // Signal handler type
static PVOID veh = NULL;
static sigh_t prev_sig = (sigh_t)SIG_ERR;
@@ -53,20 +55,22 @@
static bool asserts_disabled = false;
-int init_private_tls_data()
+static void show_debugger_dialog()
{
- DWORD key = TlsAlloc();
-
- if (key == TLS_OUT_OF_INDEXES)
- return -1;
+ int result = MessageBox(NULL,
+ "Crash handler has been 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);
- port_tls_key = key;
- return 0;
-}
+ if (result == IDCANCEL)
+ {
+ _exit(3);
+ return;
+ }
-int free_private_tls_data()
-{
- return TlsFree(port_tls_key) ? 0 : -1;
+ port_win_dbg_break(); // Call the debugger
}
@@ -74,7 +78,6 @@
void* fault_addr, size_t code, size_t flags)
{ // this exception handler is executed *after* VEH handler returned
int result;
- Registers regs = *pregs;
Boolean iscrash = (DWORD)flags == EXCEPTION_NONCONTINUABLE;
switch ((DWORD)code)
@@ -99,69 +102,127 @@
result = port_process_signal(PORT_SIGNAL_UNKNOWN, pregs, fault_addr, TRUE);
}
+ port_tls_data_t* tlsdata = get_private_tls_data();
+
if (result == 0)
+ {
+ // Restore guard page if needed
+ if (tlsdata->restore_guard_page)
+ {
+ port_thread_restore_guard_page();
+ tlsdata->restore_guard_page = FALSE;
+
+ if (port_thread_detach_temporary() == 0)
+ STD_FREE(tlsdata);
+ }
return;
+ }
- if (result > 0 || // Assert dialog
- (port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+ if (result > 0 /*Assert dialog*/|| FLAG_CORE)
{
// Prepare second catch of this exception to produce minidump (because
// we've lost LPEXCEPTION_POINTERS structure) and/or show assert dialog
- // FIXME: This will not work for stack overflow, because guard page
- // is disabled automatically - need to restore it somehow
- 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);
- }
-
- if ((port_crash_handler_get_flags() & PORT_CRASH_DUMP_PROCESS_CORE) != 0)
+ if (FLAG_CORE)
tlsdata->produce_core = TRUE;
if (result > 0)
tlsdata->debugger = TRUE;
+ // To catch STACK_OVERFLOW
+ port_thread_restore_guard_page();
return; // To produce exception again
}
- _exit(-1);
+ _exit(-1); // We need neither dump nor assert dialog
}
void prepare_assert_dialog(Registers* regs)
{
+ // To catch STACK_OVERFLOW
+ port_thread_restore_guard_page();
shutdown_signals();
}
LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception)
{
+ DWORD code = nt_exception->ExceptionRecord->ExceptionCode;
+ void* fault_addr = nt_exception->ExceptionRecord->ExceptionAddress;
+
Registers regs;
// Convert NT context to Registers
port_thread_context_to_regs(®s, nt_exception->ContextRecord);
// Check if TLS structure is set - probably we should produce minidump
- port_tls_data* tlsdata = get_private_tls_data();
+ port_tls_data_t* tlsdata = get_private_tls_data();
- if (tlsdata)
+ if (!tlsdata) // Tread is not attached - attach thread temporarily
{
- if (tlsdata->produce_core)
- {
- tlsdata->produce_core = FALSE;
- create_minidump(nt_exception);
- if (!tlsdata->debugger)
+ int res;
+ tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));
+
+ if (tlsdata) // Try to attach the thread
+ res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);
+
+ if (!tlsdata || res != 0)
+ { // Can't process correctly; perform default actions
+ if (FLAG_CORE)
+ create_minidump(nt_exception);
+
+ if (FLAG_DBG)
+ {
+ show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
_exit(-1);
+ return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
+ }
+
+ _exit(-1);
}
- if (tlsdata->debugger)
+ // SO for alien thread can't be processed out of VEH
+ if (code == STATUS_STACK_OVERFLOW &&
+ sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
{
- // Go to handler to restore CRT/VEH settings and crash once again
- port_set_longjump_regs(&prepare_assert_dialog, ®s, 1, ®s);
- port_thread_regs_to_context(nt_exception->ContextRecord, ®s);
- return EXCEPTION_CONTINUE_EXECUTION;
+ int result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, ®s, fault_addr, FALSE);
+
+ if (result == 0)
+ {
+ if (port_thread_detach_temporary() == 0)
+ STD_FREE(tlsdata);
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ if (FLAG_CORE)
+ create_minidump(nt_exception);
+
+ if (result > 0)
+ {
+ show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
+ _exit(-1);
+ shutdown_signals();
+ return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
+ }
+
+ _exit(-1);
}
}
- switch (nt_exception->ExceptionRecord->ExceptionCode)
+ if (tlsdata->produce_core)
+ {
+ create_minidump(nt_exception);
+ if (!tlsdata->debugger)
+ _exit(-1);
+ }
+
+ if (tlsdata->debugger)
+ {
+ show_debugger_dialog(); // Workaround
+ _exit(-1);
+ // Go to handler to restore CRT/VEH settings and crash once again
+// port_set_longjump_regs(&prepare_assert_dialog, ®s, 1, ®s);
+// port_thread_regs_to_context(nt_exception->ContextRecord, ®s);
+// return EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ switch (code)
{
case STATUS_STACK_OVERFLOW:
if (!sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
@@ -187,6 +248,12 @@
return EXCEPTION_CONTINUE_SEARCH;
}
+ if (code == STATUS_STACK_OVERFLOW)
+ {
+ if (!tlsdata->restore_guard_page)
+ tlsdata->restore_guard_page = TRUE;
+ }
+
// Prepare to transfering control out of VEH handler
port_set_longjump_regs(&c_handler, ®s, 4, ®s,
nt_exception->ExceptionRecord->ExceptionAddress,
@@ -258,25 +325,7 @@
#endif // _DEBUG
}
-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)
+static void PORT_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
@@ -291,7 +340,7 @@
_exit(3);
}
-static void __cdecl final_sigabrt_handler(int signum)
+static void PORT_CDECL final_sigabrt_handler(int signum)
{
_exit(3);
}
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=660062&r1=660061&r2=660062&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 Sun May 25 17:33:06 2008
@@ -36,7 +36,7 @@
}
}
-void __declspec(naked) __cdecl port_win_dbg_break()
+void __declspec(naked) PORT_CDECL port_win_dbg_break()
{
__asm { int 3 }
}
Added: harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h?rev=660062&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h Sun May 25 17:33:06 2008
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _PORT_THREAD_INTERNAL_H_
+#define _PORT_THREAD_INTERNAL_H_
+
+#include "port_general.h"
+#include "port_thread.h"
+#include "open/platform_types.h"
+#include "open/hythread_ext.h" /* For windows.h */
+/* UNIX-specific includes */
+#ifndef WIN32
+#include <semaphore.h>
+#endif
+
+/* The name of Port shared library - now crash handler module */
+#define CH_SHLIB_NAME "ch"
+
+#ifdef WIN32
+typedef DWORD port_tls_key_t;
+#else
+typedef pthread_key_t port_tls_key_t;
+#endif
+
+typedef enum
+{
+ THREADREQ_NONE = 0,
+ THREADREQ_SUS = 1,
+ THREADREQ_RES = 2,
+ THREADREQ_YIELD = 3
+} port_suspend_req_t;
+
+
+typedef struct port_thread_info_t port_thread_info_t;
+struct port_thread_info_t
+{
+ osthread_t thread;
+ thread_context_t context;
+ int suspend_count;
+#ifndef WIN32
+ sem_t wake_sem; /* to sem_post from signal handler */
+#endif /* !WIN32 */
+ port_thread_info_t* next;
+};
+
+
+typedef struct
+{
+ port_tls_key_t tls_key;
+
+ size_t guard_page_size;
+ size_t guard_stack_size;
+ size_t mem_protect_size;
+ size_t foreign_stack_size;
+
+ /* Stuff for suspend/resume handling */
+ port_thread_info_t* suspended_list;
+#ifdef WIN32
+ CRITICAL_SECTION crit_section;
+#else /* !WIN32 */
+ pthread_mutex_t suspend_init_mutex;
+ pthread_mutex_t suspend_mutex;
+ port_suspend_req_t req_type; /* request type for signal handler */
+ osthread_t suspendee; /* The thread which is processed */
+ sem_t yield_sem; /* Semaphore to inform signal sender */
+ Boolean signal_set; /* Is SIGUSR2 handler set up */
+#endif /* !WIN32 */
+
+} port_shared_data_t;
+
+
+/* Thread-specific structure */
+typedef struct
+{
+ /* vv Threading stuff vv */
+ void* stack_addr;
+ size_t stack_size;
+ void* guard_page_addr;
+ size_t guard_page_size;
+ void* guard_stack_addr;
+ size_t guard_stack_size;
+ size_t mem_protect_size;
+
+ Boolean guard_page_set;
+ Boolean restore_guard_page;
+
+ Boolean foreign; /* The thread was attached */
+ //Boolean temp; /* Is indicated by 0ed guard_page_addr instead */
+
+ /* vv Signal handling stuff vv */
+#ifndef WIN32 /* UNIX */
+ /* Flag and restart address for memory access violation detection */
+ int violation_flag;
+ void* restart_address;
+#endif /* UNIX */
+
+ /* vv Crash handling stuff vv */
+ /* Previous crash handling stage to restart crash processing */
+ int crash_stage;
+
+ /* 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;
+
+} port_tls_data_t;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern volatile port_shared_data_t* port_shared_data;
+#define PSD ((port_shared_data_t*)port_shared_data)
+
+int init_port_shared_data();
+
+
+PORT_INLINE port_tls_data_t* get_private_tls_data()
+{
+ if (!port_shared_data && init_port_shared_data() != 0)
+ return NULL;
+#ifdef WIN32
+ return (port_tls_data_t*)TlsGetValue(port_shared_data->tls_key);
+#else
+ return (port_tls_data_t*)pthread_getspecific(port_shared_data->tls_key);
+#endif
+}
+
+PORT_INLINE int set_private_tls_data(port_tls_data_t* data)
+{
+ if (!port_shared_data && init_port_shared_data() != 0)
+ return -1;
+#ifdef WIN32
+ return TlsSetValue(port_shared_data->tls_key, data) ? 0 : -1;
+#else
+ return pthread_setspecific(port_shared_data->tls_key, data);
+#endif
+}
+
+
+/* Is used in both threading and signals */
+int port_thread_attach_local(port_tls_data_t* tlsdata, Boolean temp,
+ Boolean foreign, size_t stack_size);
+/* Detaches temporarily attached thread */
+int port_thread_detach_temporary();
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PORT_THREAD_INTERNAL_H_ */
Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/thread/include/port_thread_internal.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c?rev=660062&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c Sun May 25 17:33:06 2008
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dlfcn.h>
+#include "port_thread_internal.h"
+
+
+#define SHPORT_SH_NAME ("lib" CH_SHLIB_NAME ".so")
+
+volatile port_shared_data_t* port_shared_data = NULL;
+
+typedef int (*fn_port_init_shared_data_t)(volatile port_shared_data_t** pdata);
+
+
+int init_port_shared_data()
+{
+ void* native_handle;
+ fn_port_init_shared_data_t fn_ptr;
+
+ if (port_shared_data)
+ return 0;
+
+ native_handle = dlopen(SHPORT_SH_NAME, RTLD_NOW | RTLD_GLOBAL);
+
+ if (native_handle == NULL)
+ return -1;
+
+ fn_ptr =
+ (fn_port_init_shared_data_t)dlsym(native_handle, "port_init_shared_data");
+
+ if (!fn_ptr)
+ return -1;
+
+ return fn_ptr(&port_shared_data);
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_find.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c?rev=660062&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c (added)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c Sun May 25 17:33:06 2008
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef __USE_XOPEN
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+#include "port_mutex.h"
+#include "port_atomic.h"
+#include "port_thread_internal.h"
+
+volatile port_shared_data_t* port_shared_data = NULL;
+
+static pthread_mutex_t g_shared_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+static port_shared_data_t* g_port_shared_data = NULL;
+static port_shared_data_t g_port_shared_data_struct;
+
+#ifdef _EM64T_
+#define MEM_PROTECT_SIZE 0x400
+#elif defined (_IPF_)
+#define MEM_PROTECT_SIZE 0
+#else /* _IA32_ */
+#define MEM_PROTECT_SIZE 0x100
+#endif
+
+static int init_psd_structure(port_shared_data_t* data)
+{
+ int err;
+ pthread_attr_t pthread_attr;
+ size_t stack_size, guard_size;
+
+ memset(data, 0, sizeof(port_shared_data_t));
+
+ if ((err = pthread_key_create(&data->tls_key, NULL)) != 0)
+ return err;
+
+ if ((err = pthread_mutex_init(&data->suspend_mutex, NULL)) != 0)
+ return err;
+
+ if ((err = pthread_mutex_init(&data->suspend_init_mutex, NULL)) != 0)
+ return err;
+
+ pthread_attr_init(&pthread_attr);
+ err = pthread_attr_getstacksize(&pthread_attr, &stack_size);
+ pthread_attr_destroy(&pthread_attr);
+
+ if (err != 0)
+ return err;
+
+ pthread_attr_init(&pthread_attr);
+ err = pthread_attr_getguardsize(&pthread_attr, &guard_size);
+ pthread_attr_destroy(&pthread_attr);
+
+ if (err != 0)
+ return err;
+
+ if (sem_init(&data->yield_sem, 0, 0) != 0)
+ return err;
+
+ data->foreign_stack_size = stack_size;
+ data->guard_page_size = guard_size;
+ data->mem_protect_size = MEM_PROTECT_SIZE;
+ data->req_type = THREADREQ_NONE;
+ data->signal_set = FALSE;
+
+ data->guard_stack_size = 64*1024;
+
+ if (data->guard_stack_size < MINSIGSTKSZ)
+ data->guard_stack_size =
+ (MINSIGSTKSZ + guard_size - 1) & ~(guard_size - 1);
+
+ return 0;
+}
+
+int port_init_shared_data(volatile port_shared_data_t** p_psd)
+{
+ int err = 0;
+
+ if (*p_psd)
+ return 0;
+
+ /* Serialize access to avoid multiple initialization */
+ err = pthread_mutex_lock(&g_shared_data_mutex);
+
+ if (err != 0)
+ return err;
+
+ /* If another thread had filled the pointer */
+ if (*p_psd)
+ {
+ pthread_mutex_unlock(&g_shared_data_mutex);
+ return 0;
+ }
+
+ /* If structure is already initialized */
+ if (!g_port_shared_data)
+ {
+ err = init_psd_structure(&g_port_shared_data_struct);
+
+ if (err == 0)
+ g_port_shared_data = &g_port_shared_data_struct;
+ }
+
+ if (g_port_shared_data)
+ *p_psd = g_port_shared_data;
+
+ pthread_mutex_unlock(&g_shared_data_mutex);
+ return err;
+}
+
+
+int init_port_shared_data()
+{
+ if (port_shared_data)
+ return 0;
+
+ return port_init_shared_data(&port_shared_data);
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/port/src/thread/linux/port_thread_tls_os.c
------------------------------------------------------------------------------
svn:eol-style = native