2 * mini-posix.c: POSIX signal handling support for Mono.
5 * Mono Team (mono-list@lists.ximian.com)
7 * Copyright 2001-2003 Ximian, Inc.
8 * Copyright 2003-2008 Ximian, Inc.
10 * See LICENSE for licensing information.
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
17 #include <mono/metadata/assembly.h>
18 #include <mono/metadata/loader.h>
19 #include <mono/metadata/tabledefs.h>
20 #include <mono/metadata/class.h>
21 #include <mono/metadata/object.h>
22 #include <mono/metadata/tokentype.h>
23 #include <mono/metadata/tabledefs.h>
24 #include <mono/metadata/threads.h>
25 #include <mono/metadata/appdomain.h>
26 #include <mono/metadata/debug-helpers.h>
27 #include <mono/io-layer/io-layer.h>
28 #include "mono/metadata/profiler.h"
29 #include <mono/metadata/profiler-private.h>
30 #include <mono/metadata/mono-config.h>
31 #include <mono/metadata/environment.h>
32 #include <mono/metadata/mono-debug.h>
33 #include <mono/metadata/gc-internals.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/verify.h>
36 #include <mono/metadata/verify-internals.h>
37 #include <mono/metadata/mempool-internals.h>
38 #include <mono/metadata/attach.h>
39 #include <mono/utils/mono-math.h>
40 #include <mono/utils/mono-compiler.h>
41 #include <mono/utils/mono-counters.h>
42 #include <mono/utils/mono-logger-internals.h>
43 #include <mono/utils/mono-mmap.h>
44 #include <mono/utils/dtrace.h>
47 #include "mini-windows.h"
53 #include "jit-icalls.h"
55 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
60 mono_runtime_install_handlers (void)
62 #ifndef MONO_CROSS_COMPILE
64 win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
65 win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
66 win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
67 if (mini_get_debug_options ()->handle_sigint)
68 win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
73 mono_runtime_cleanup_handlers (void)
75 #ifndef MONO_CROSS_COMPILE
83 * Call the original signal handler for the signal given by the arguments, which
84 * should be the same as for a signal handler. Returns TRUE if the original handler
85 * was called, false otherwise.
88 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
90 MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
91 jit_tls->mono_win_chained_exception_needs_run = TRUE;
95 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
96 static MMRESULT g_timer_event = 0;
97 static HANDLE g_timer_main_thread = INVALID_HANDLE_VALUE;
100 thread_timer_expired (HANDLE thread)
104 context.ContextFlags = CONTEXT_CONTROL;
105 if (GetThreadContext (thread, &context)) {
107 mono_profiler_stat_hit ((guchar *) context.Rip, &context);
109 mono_profiler_stat_hit ((guchar *) context.Eip, &context);
115 timer_event_proc (UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
117 thread_timer_expired ((HANDLE)dwUser);
121 stop_profiler_timer_event (void)
123 if (g_timer_event != 0) {
125 timeKillEvent (g_timer_event);
129 if (g_timer_main_thread != INVALID_HANDLE_VALUE) {
131 CloseHandle (g_timer_main_thread);
132 g_timer_main_thread = INVALID_HANDLE_VALUE;
137 start_profiler_timer_event (void)
139 g_return_if_fail (g_timer_main_thread == INVALID_HANDLE_VALUE && g_timer_event == 0);
143 if (timeGetDevCaps (&timecaps, sizeof (timecaps)) != TIMERR_NOERROR)
146 g_timer_main_thread = OpenThread (READ_CONTROL | THREAD_GET_CONTEXT, FALSE, GetCurrentThreadId ());
147 if (g_timer_main_thread == NULL)
150 if (timeBeginPeriod (1) != TIMERR_NOERROR)
153 g_timer_event = timeSetEvent (1, 0, (LPTIMECALLBACK)timer_event_proc, (DWORD_PTR)g_timer_main_thread, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
154 if (g_timer_event == 0) {
161 mono_runtime_setup_stat_profiler (void)
163 start_profiler_timer_event ();
168 mono_runtime_shutdown_stat_profiler (void)
170 stop_profiler_timer_event ();
175 mono_setup_thread_context(DWORD thread_id, MonoContext *mono_context)
180 g_assert (thread_id != GetCurrentThreadId ());
182 handle = OpenThread (THREAD_ALL_ACCESS, FALSE, thread_id);
185 context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
187 if (!GetThreadContext (handle, &context)) {
188 CloseHandle (handle);
192 g_assert (context.ContextFlags & CONTEXT_INTEGER);
193 g_assert (context.ContextFlags & CONTEXT_CONTROL);
195 memset (mono_context, 0, sizeof (MonoContext));
196 mono_sigctx_to_monoctx (&context, mono_context);
198 CloseHandle (handle);
201 #endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
204 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info)
206 DWORD id = mono_thread_info_get_tid (info);
207 MonoJitTlsData *jit_tls;
213 tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = NULL;
214 tctx->unwind_data [MONO_UNWIND_DATA_LMF] = NULL;
215 tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL;
217 mono_setup_thread_context(id, &tctx->ctx);
219 /* mono_set_jit_tls () sets this */
220 jit_tls = mono_thread_info_tls_get (info, TLS_KEY_JIT_TLS);
221 /* SET_APPDOMAIN () sets this */
222 domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN);
224 /*Thread already started to cleanup, can no longer capture unwind state*/
225 if (!jit_tls || !domain)
229 * The current LMF address is kept in a separate TLS variable, and its hard to read its value without
230 * arch-specific code. But the address of the TLS variable is stored in another TLS variable which
231 * can be accessed through MonoThreadInfo.
233 /* mono_set_lmf_addr () sets this */
234 addr = mono_thread_info_tls_get (info, TLS_KEY_LMF_ADDR);
238 tctx->unwind_data [MONO_UNWIND_DATA_DOMAIN] = domain;
239 tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = jit_tls;
240 tctx->unwind_data [MONO_UNWIND_DATA_LMF] = lmf;