9a2317b8ec79c788c650bf0ed54be997ddd13cf0
[mono.git] / mono / mini / mini-posix.c
1 /*
2  * mini-posix.c: POSIX signal handling support for Mono.
3  *
4  * Authors:
5  *   Mono Team (mono-list@lists.ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc.
8  * Copyright 2003-2008 Ximian, Inc.
9  *
10  * See LICENSE for licensing information.
11  */
12 #include <config.h>
13 #include <signal.h>
14 #ifdef HAVE_ALLOCA_H
15 #include <alloca.h>
16 #endif
17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h>
19 #endif
20 #include <math.h>
21 #ifdef HAVE_SYS_TIME_H
22 #include <sys/time.h>
23 #endif
24 #ifdef HAVE_SYS_SYSCALL_H
25 #include <sys/syscall.h>
26 #endif
27
28 #include <mono/metadata/assembly.h>
29 #include <mono/metadata/loader.h>
30 #include <mono/metadata/tabledefs.h>
31 #include <mono/metadata/class.h>
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/tokentype.h>
34 #include <mono/metadata/tabledefs.h>
35 #include <mono/metadata/threads.h>
36 #include <mono/metadata/appdomain.h>
37 #include <mono/metadata/debug-helpers.h>
38 #include <mono/io-layer/io-layer.h>
39 #include "mono/metadata/profiler.h"
40 #include <mono/metadata/profiler-private.h>
41 #include <mono/metadata/mono-config.h>
42 #include <mono/metadata/environment.h>
43 #include <mono/metadata/mono-debug.h>
44 #include <mono/metadata/gc-internal.h>
45 #include <mono/metadata/threads-types.h>
46 #include <mono/metadata/verify.h>
47 #include <mono/metadata/verify-internals.h>
48 #include <mono/metadata/mempool-internals.h>
49 #include <mono/metadata/attach.h>
50 #include <mono/utils/mono-math.h>
51 #include <mono/utils/mono-compiler.h>
52 #include <mono/utils/mono-counters.h>
53 #include <mono/utils/mono-logger.h>
54 #include <mono/utils/mono-mmap.h>
55 #include <mono/utils/dtrace.h>
56
57 #include "mini.h"
58 #include <string.h>
59 #include <ctype.h>
60 #include "trace.h"
61 #include "version.h"
62 #include "debugger-agent.h"
63
64 #include "jit-icalls.h"
65
66 static GHashTable *mono_saved_signal_handlers = NULL;
67
68 static gpointer
69 get_saved_signal_handler (int signo)
70 {
71         if (mono_saved_signal_handlers)
72                 /* The hash is only modified during startup, so no need for locking */
73                 return g_hash_table_lookup (mono_saved_signal_handlers, GINT_TO_POINTER (signo));
74         return NULL;
75 }
76
77 static void
78 save_old_signal_handler (int signo, struct sigaction *old_action)
79 {
80         struct sigaction *handler_to_save = g_malloc (sizeof (struct sigaction));
81
82         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_CONFIG,
83                                 "Saving old signal handler for signal %d.", signo);
84
85         if (! (old_action->sa_flags & SA_SIGINFO)) {
86                 handler_to_save->sa_handler = old_action->sa_handler;
87         } else {
88 #ifdef MONO_ARCH_USE_SIGACTION
89                 handler_to_save->sa_sigaction = old_action->sa_sigaction;
90 #endif /* MONO_ARCH_USE_SIGACTION */
91         }
92         handler_to_save->sa_mask = old_action->sa_mask;
93         handler_to_save->sa_flags = old_action->sa_flags;
94         
95         if (!mono_saved_signal_handlers)
96                 mono_saved_signal_handlers = g_hash_table_new (NULL, NULL);
97         g_hash_table_insert (mono_saved_signal_handlers, GINT_TO_POINTER (signo), handler_to_save);
98 }
99
100 static void
101 free_saved_sig_handler_func (gpointer key, gpointer value, gpointer user_data)
102 {
103         g_free (value);
104 }
105
106 static void
107 free_saved_signal_handlers (void)
108 {
109         if (mono_saved_signal_handlers) {
110                 g_hash_table_foreach (mono_saved_signal_handlers, free_saved_sig_handler_func, NULL);
111                 g_hash_table_destroy (mono_saved_signal_handlers);
112                 mono_saved_signal_handlers = NULL;
113         }
114 }
115
116 /*
117  * mono_chain_signal:
118  *
119  *   Call the original signal handler for the signal given by the arguments, which
120  * should be the same as for a signal handler. Returns TRUE if the original handler
121  * was called, false otherwise.
122  */
123 gboolean
124 SIG_HANDLER_SIGNATURE (mono_chain_signal)
125 {
126         int signal = _dummy;
127         struct sigaction *saved_handler = get_saved_signal_handler (signal);
128
129         GET_CONTEXT;
130
131         if (saved_handler) {
132                 if (!(saved_handler->sa_flags & SA_SIGINFO)) {
133                         saved_handler->sa_handler (signal);
134                 } else {
135 #ifdef MONO_ARCH_USE_SIGACTION
136                         saved_handler->sa_sigaction (signal, info, ctx);
137 #endif /* MONO_ARCH_USE_SIGACTION */
138                 }
139                 return TRUE;
140         }
141         return FALSE;
142 }
143
144 static void
145 SIG_HANDLER_SIGNATURE (sigabrt_signal_handler)
146 {
147         MonoJitInfo *ji = NULL;
148         GET_CONTEXT;
149
150         if (mono_thread_internal_current ())
151                 ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
152         if (!ji) {
153         if (mono_chain_signal (SIG_HANDLER_PARAMS))
154                         return;
155                 mono_handle_native_sigsegv (SIGABRT, ctx);
156         }
157 }
158
159 static void
160 SIG_HANDLER_SIGNATURE (sigusr1_signal_handler)
161 {
162         gboolean running_managed;
163         MonoException *exc;
164         MonoInternalThread *thread = mono_thread_internal_current ();
165         MonoDomain *domain = mono_domain_get ();
166         void *ji;
167         
168         GET_CONTEXT;
169
170         if (!thread || !domain)
171                 /* The thread might not have started up yet */
172                 /* FIXME: Specify the synchronization with start_wrapper () in threads.c */
173                 return;
174
175         if (thread->thread_dump_requested) {
176                 thread->thread_dump_requested = FALSE;
177
178                 mono_print_thread_dump (ctx);
179         }
180
181         /*
182          * FIXME:
183          * This is an async signal, so the code below must not call anything which
184          * is not async safe. That includes the pthread locking functions. If we
185          * know that we interrupted managed code, then locking is safe.
186          */
187         ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx));
188         running_managed = ji != NULL;
189
190         if (mono_debugger_agent_thread_interrupt (ctx, ji))
191                 return;
192         
193         exc = mono_thread_request_interruption (running_managed); 
194         if (!exc)
195                 return;
196
197         mono_arch_handle_exception (ctx, exc, FALSE);
198 }
199
200 #if defined(__i386__) || defined(__x86_64__)
201 #define FULL_STAT_PROFILER_BACKTRACE 1
202 #define CURRENT_FRAME_GET_BASE_POINTER(f) (* (gpointer*)(f))
203 #define CURRENT_FRAME_GET_RETURN_ADDRESS(f) (* (((gpointer*)(f)) + 1))
204 #if MONO_ARCH_STACK_GROWS_UP
205 #define IS_BEFORE_ON_STACK <
206 #define IS_AFTER_ON_STACK >
207 #else
208 #define IS_BEFORE_ON_STACK >
209 #define IS_AFTER_ON_STACK <
210 #endif
211 #else
212 #define FULL_STAT_PROFILER_BACKTRACE 0
213 #endif
214
215 #if defined(__ia64__) || defined(__sparc__) || defined(sparc) || defined(__s390__) || defined(s390)
216
217 static void
218 SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
219 {
220         if (mono_chain_signal (SIG_HANDLER_PARAMS))
221                 return;
222
223         NOT_IMPLEMENTED;
224 }
225
226 #else
227
228 static void
229 SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
230 {
231         int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
232         MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
233         GET_CONTEXT;
234         
235         if (call_chain_depth == 0) {
236                 mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx);
237         } else {
238                 MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
239                 int current_frame_index = 1;
240                 MonoContext mono_context;
241                 guchar *ips [call_chain_depth + 1];
242
243                 mono_arch_sigctx_to_monoctx (ctx, &mono_context);
244                 ips [0] = MONO_CONTEXT_GET_IP (&mono_context);
245                 
246                 if (jit_tls != NULL) {
247                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
248 #if FULL_STAT_PROFILER_BACKTRACE
249                         guchar *current_frame;
250                         guchar *stack_bottom;
251                         guchar *stack_top;
252                         
253                         stack_bottom = jit_tls->end_of_stack;
254                         stack_top = MONO_CONTEXT_GET_SP (&mono_context);
255                         current_frame = MONO_CONTEXT_GET_BP (&mono_context);
256                         
257                         while ((current_frame_index <= call_chain_depth) &&
258                                         (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
259                                         ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
260                                 ips [current_frame_index] = CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
261                                 current_frame_index ++;
262                                 stack_top = current_frame;
263                                 current_frame = CURRENT_FRAME_GET_BASE_POINTER (current_frame);
264                         }
265 #else
266                                 call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
267 #endif
268                         }
269                         
270                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
271 #if GLIBC_PROFILER_BACKTRACE
272                                 current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
273 #else
274                                 call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
275 #endif
276                         }
277
278                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
279                                 MonoDomain *domain = mono_domain_get ();
280                                 if (domain != NULL) {
281                                         MonoLMF *lmf = NULL;
282                                         MonoJitInfo *ji;
283                                         MonoJitInfo res;
284                                         MonoContext new_mono_context;
285                                         int native_offset;
286                                         ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
287                                                         &new_mono_context, NULL, &lmf, &native_offset, NULL);
288                                         while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
289                                                 ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context);
290                                                 current_frame_index ++;
291                                                 mono_context = new_mono_context;
292                                                 ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
293                                                                 &new_mono_context, NULL, &lmf, &native_offset, NULL);
294                                         }
295                                 }
296                         }
297                 }
298                 
299                 mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
300         }
301
302         mono_chain_signal (SIG_HANDLER_PARAMS);
303 }
304
305 #endif
306
307 static void
308 SIG_HANDLER_SIGNATURE (sigquit_signal_handler)
309 {
310         gboolean res;
311
312         GET_CONTEXT;
313
314         /* We use this signal to start the attach agent too */
315         res = mono_attach_start ();
316         if (res)
317                 return;
318
319         printf ("Full thread dump:\n");
320
321         mono_threads_request_thread_dump ();
322
323         /*
324          * print_thread_dump () skips the current thread, since sending a signal
325          * to it would invoke the signal handler below the sigquit signal handler,
326          * and signal handlers don't create an lmf, so the stack walk could not
327          * be performed.
328          */
329         mono_print_thread_dump (ctx);
330
331         mono_chain_signal (SIG_HANDLER_PARAMS);
332 }
333
334 static void
335 SIG_HANDLER_SIGNATURE (sigusr2_signal_handler)
336 {
337         gboolean enabled = mono_trace_is_enabled ();
338
339         mono_trace_enable (!enabled);
340
341         mono_chain_signal (SIG_HANDLER_PARAMS);
342 }
343
344 static void
345 add_signal_handler (int signo, gpointer handler)
346 {
347         struct sigaction sa;
348         struct sigaction previous_sa;
349
350 #ifdef MONO_ARCH_USE_SIGACTION
351         sa.sa_sigaction = handler;
352         sigemptyset (&sa.sa_mask);
353         sa.sa_flags = SA_SIGINFO;
354 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
355         if (signo == SIGSEGV) {
356                 sa.sa_flags |= SA_ONSTACK;
357
358                 /* 
359                  * libgc will crash when trying to do stack marking for threads which are on
360                  * an altstack, so delay the suspend signal after the signal handler has
361                  * executed.
362                  */
363                 if (mono_gc_get_suspend_signal () != -1)
364                         sigaddset (&sa.sa_mask, mono_gc_get_suspend_signal ());
365         }
366 #endif
367         if (signo == SIGSEGV) {
368                 /* 
369                  * Delay abort signals while handling SIGSEGVs since they could go unnoticed.
370                  */
371                 sigset_t block_mask;
372      
373                 sigemptyset (&block_mask);
374                 sigaddset (&sa.sa_mask, mono_thread_get_abort_signal ());
375         }
376 #else
377         sa.sa_handler = handler;
378         sigemptyset (&sa.sa_mask);
379         sa.sa_flags = 0;
380 #endif
381         g_assert (sigaction (signo, &sa, &previous_sa) != -1);
382
383         /* if there was already a handler in place for this signal, store it */
384         if (! (previous_sa.sa_flags & SA_SIGINFO) &&
385                         (SIG_DFL == previous_sa.sa_handler)) { 
386                 /* it there is no sa_sigaction function and the sa_handler is default, we can safely ignore this */
387         } else {
388                 if (mono_do_signal_chaining)
389                         save_old_signal_handler (signo, &previous_sa);
390         }
391 }
392
393 static void
394 remove_signal_handler (int signo)
395 {
396         struct sigaction sa;
397         struct sigaction *saved_action = get_saved_signal_handler (signo);
398
399         if (!saved_action) {
400                 sa.sa_handler = SIG_DFL;
401                 sigemptyset (&sa.sa_mask);
402                 sa.sa_flags = 0;
403
404                 sigaction (signo, &sa, NULL);
405         } else {
406                 g_assert (sigaction (signo, saved_action, NULL) != -1);
407         }
408 }
409
410 void
411 mono_runtime_posix_install_handlers (void)
412 {
413
414         sigset_t signal_set;
415
416         if (mini_get_debug_options ()->handle_sigint)
417                 add_signal_handler (SIGINT, mono_sigint_signal_handler);
418
419         add_signal_handler (SIGFPE, mono_sigfpe_signal_handler);
420         add_signal_handler (SIGQUIT, sigquit_signal_handler);
421         add_signal_handler (SIGILL, mono_sigill_signal_handler);
422         add_signal_handler (SIGBUS, mono_sigsegv_signal_handler);
423         if (mono_jit_trace_calls != NULL)
424                 add_signal_handler (SIGUSR2, sigusr2_signal_handler);
425
426         add_signal_handler (mono_thread_get_abort_signal (), sigusr1_signal_handler);
427         /* it seems to have become a common bug for some programs that run as parents
428          * of many processes to block signal delivery for real time signals.
429          * We try to detect and work around their breakage here.
430          */
431         sigemptyset (&signal_set);
432         sigaddset (&signal_set, mono_thread_get_abort_signal ());
433         sigprocmask (SIG_UNBLOCK, &signal_set, NULL);
434
435         signal (SIGPIPE, SIG_IGN);
436
437         add_signal_handler (SIGABRT, sigabrt_signal_handler);
438
439         /* catch SIGSEGV */
440         add_signal_handler (SIGSEGV, mono_sigsegv_signal_handler);
441 }
442
443 #ifndef PLATFORM_MACOSX
444 void
445 mono_runtime_install_handlers (void)
446 {
447         mono_runtime_posix_install_handlers ();
448 }
449 #endif
450
451 void
452 mono_runtime_cleanup_handlers (void)
453 {
454         if (mini_get_debug_options ()->handle_sigint)
455                 remove_signal_handler (SIGINT);
456
457         remove_signal_handler (SIGFPE);
458         remove_signal_handler (SIGQUIT);
459         remove_signal_handler (SIGILL);
460         remove_signal_handler (SIGBUS);
461         if (mono_jit_trace_calls != NULL)
462                 remove_signal_handler (SIGUSR2);
463
464         remove_signal_handler (mono_thread_get_abort_signal ());
465
466         remove_signal_handler (SIGABRT);
467
468         remove_signal_handler (SIGSEGV);
469
470         free_saved_signal_handlers ();
471 }
472
473 #ifdef HAVE_LINUX_RTC_H
474 #include <linux/rtc.h>
475 #include <sys/ioctl.h>
476 #include <fcntl.h>
477 static int rtc_fd = -1;
478
479 static int
480 enable_rtc_timer (gboolean enable)
481 {
482         int flags;
483         flags = fcntl (rtc_fd, F_GETFL);
484         if (flags < 0) {
485                 perror ("getflags");
486                 return 0;
487         }
488         if (enable)
489                 flags |= FASYNC;
490         else
491                 flags &= ~FASYNC;
492         if (fcntl (rtc_fd, F_SETFL, flags) == -1) {
493                 perror ("setflags");
494                 return 0;
495         }
496         return 1;
497 }
498 #endif
499
500 void
501 mono_runtime_shutdown_stat_profiler (void)
502 {
503 #ifdef HAVE_LINUX_RTC_H
504         if (rtc_fd >= 0)
505                 enable_rtc_timer (FALSE);
506 #endif
507 }
508
509 void
510 mono_runtime_setup_stat_profiler (void)
511 {
512 #ifdef ITIMER_PROF
513         struct itimerval itval;
514         static int inited = 0;
515 #ifdef HAVE_LINUX_RTC_H
516         const char *rtc_freq;
517         if (!inited && (rtc_freq = g_getenv ("MONO_RTC"))) {
518                 int freq = 0;
519                 inited = 1;
520                 if (*rtc_freq)
521                         freq = atoi (rtc_freq);
522                 if (!freq)
523                         freq = 1024;
524                 rtc_fd = open ("/dev/rtc", O_RDONLY);
525                 if (rtc_fd == -1) {
526                         perror ("open /dev/rtc");
527                         return;
528                 }
529                 add_signal_handler (SIGPROF, sigprof_signal_handler);
530                 if (ioctl (rtc_fd, RTC_IRQP_SET, freq) == -1) {
531                         perror ("set rtc freq");
532                         return;
533                 }
534                 if (ioctl (rtc_fd, RTC_PIE_ON, 0) == -1) {
535                         perror ("start rtc");
536                         return;
537                 }
538                 if (fcntl (rtc_fd, F_SETSIG, SIGPROF) == -1) {
539                         perror ("setsig");
540                         return;
541                 }
542                 if (fcntl (rtc_fd, F_SETOWN, getpid ()) == -1) {
543                         perror ("setown");
544                         return;
545                 }
546                 enable_rtc_timer (TRUE);
547                 return;
548         }
549         if (rtc_fd >= 0)
550                 return;
551 #endif
552
553         itval.it_interval.tv_usec = 999;
554         itval.it_interval.tv_sec = 0;
555         itval.it_value = itval.it_interval;
556         setitimer (ITIMER_PROF, &itval, NULL);
557         if (inited)
558                 return;
559         inited = 1;
560         add_signal_handler (SIGPROF, sigprof_signal_handler);
561 #endif
562 }
563
564 #if !defined(__APPLE__)
565 pid_t
566 mono_runtime_syscall_fork ()
567 {
568 #if defined(SYS_fork)
569         return (pid_t) syscall (SYS_fork);
570 #else
571         g_assert_not_reached ();
572         return;
573 #endif
574 }
575
576 gboolean
577 mono_gdb_render_native_backtraces ()
578 {
579         const char *argv [9];
580         char buf1 [128];
581
582         argv [0] = g_find_program_in_path ("gdb");
583         if (argv [0] == NULL) {
584                 return FALSE;
585         }
586
587         argv [1] = "-ex";
588         sprintf (buf1, "attach %ld", (long)getpid ());
589         argv [2] = buf1;
590         argv [3] = "--ex";
591         argv [4] = "info threads";
592         argv [5] = "--ex";
593         argv [6] = "thread apply all bt";
594         argv [7] = "--batch";
595         argv [8] = 0;
596
597         execv (argv [0], (char**)argv);
598
599         return TRUE;
600 }
601 #endif