ba60bd9934a62f109dc6698bf24ad129796ebf51
[mono.git] / mono / mini / mini-posix.c
1 /**
2  * \file
3  * POSIX signal handling support for Mono.
4  *
5  * Authors:
6  *   Mono Team (mono-list@lists.ximian.com)
7  *
8  * Copyright 2001-2003 Ximian, Inc.
9  * Copyright 2003-2008 Ximian, Inc.
10  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
11  *
12  * See LICENSE for licensing information.
13  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
14  */
15 #include <config.h>
16 #include <signal.h>
17 #ifdef HAVE_ALLOCA_H
18 #include <alloca.h>
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #include <math.h>
24 #ifdef HAVE_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27 #ifdef HAVE_SYS_SYSCALL_H
28 #include <sys/syscall.h>
29 #endif
30 #include <errno.h>
31 #include <sched.h>
32
33 #include <mono/metadata/assembly.h>
34 #include <mono/metadata/loader.h>
35 #include <mono/metadata/tabledefs.h>
36 #include <mono/metadata/class.h>
37 #include <mono/metadata/object.h>
38 #include <mono/metadata/tokentype.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/appdomain.h>
42 #include <mono/metadata/debug-helpers.h>
43 #include "mono/metadata/profiler.h"
44 #include <mono/metadata/profiler-private.h>
45 #include <mono/metadata/mono-config.h>
46 #include <mono/metadata/environment.h>
47 #include <mono/metadata/mono-debug.h>
48 #include <mono/metadata/gc-internals.h>
49 #include <mono/metadata/threads-types.h>
50 #include <mono/metadata/verify.h>
51 #include <mono/metadata/verify-internals.h>
52 #include <mono/metadata/mempool-internals.h>
53 #include <mono/metadata/attach.h>
54 #include <mono/utils/mono-math.h>
55 #include <mono/utils/mono-compiler.h>
56 #include <mono/utils/mono-counters.h>
57 #include <mono/utils/mono-logger-internals.h>
58 #include <mono/utils/mono-mmap.h>
59 #include <mono/utils/dtrace.h>
60 #include <mono/utils/mono-signal-handler.h>
61 #include <mono/utils/mono-threads.h>
62
63 #include "mini.h"
64 #include <string.h>
65 #include <ctype.h>
66 #include "trace.h"
67 #include "version.h"
68 #include "debugger-agent.h"
69
70 #include "jit-icalls.h"
71
72 #ifdef PLATFORM_MACOSX
73 #include <mach/mach.h>
74 #include <mach/mach_time.h>
75 #include <mach/clock.h>
76 #endif
77
78 #if defined(HOST_WATCHOS)
79
80 void
81 mono_runtime_setup_stat_profiler (void)
82 {
83         printf("WARNING: mono_runtime_setup_stat_profiler() called!\n");
84 }
85
86
87 void
88 mono_runtime_shutdown_stat_profiler (void)
89 {
90 }
91
92
93 gboolean
94 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
95 {
96         return FALSE;
97 }
98
99 #ifndef PLATFORM_MACOSX
100 void
101 mono_runtime_install_handlers (void)
102 {
103 }
104 #endif
105
106 void
107 mono_runtime_posix_install_handlers(void)
108 {
109         /* we still need to ignore SIGPIPE */
110         signal (SIGPIPE, SIG_IGN);
111 }
112
113 void
114 mono_runtime_shutdown_handlers (void)
115 {
116 }
117
118 void
119 mono_runtime_cleanup_handlers (void)
120 {
121 }
122
123 #else
124
125 static GHashTable *mono_saved_signal_handlers = NULL;
126
127 static struct sigaction *
128 get_saved_signal_handler (int signo, gboolean remove)
129 {
130         if (mono_saved_signal_handlers) {
131                 /* The hash is only modified during startup, so no need for locking */
132                 struct sigaction *handler = g_hash_table_lookup (mono_saved_signal_handlers, GINT_TO_POINTER (signo));
133                 if (remove && handler)
134                         g_hash_table_remove (mono_saved_signal_handlers, GINT_TO_POINTER (signo));
135                 return handler;
136         }
137         return NULL;
138 }
139
140 static void
141 save_old_signal_handler (int signo, struct sigaction *old_action)
142 {
143         struct sigaction *handler_to_save = (struct sigaction *)g_malloc (sizeof (struct sigaction));
144
145         mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_CONFIG,
146                                 "Saving old signal handler for signal %d.", signo);
147
148         if (! (old_action->sa_flags & SA_SIGINFO)) {
149                 handler_to_save->sa_handler = old_action->sa_handler;
150         } else {
151 #ifdef MONO_ARCH_USE_SIGACTION
152                 handler_to_save->sa_sigaction = old_action->sa_sigaction;
153 #endif /* MONO_ARCH_USE_SIGACTION */
154         }
155         handler_to_save->sa_mask = old_action->sa_mask;
156         handler_to_save->sa_flags = old_action->sa_flags;
157         
158         if (!mono_saved_signal_handlers)
159                 mono_saved_signal_handlers = g_hash_table_new_full (NULL, NULL, NULL, g_free);
160         g_hash_table_insert (mono_saved_signal_handlers, GINT_TO_POINTER (signo), handler_to_save);
161 }
162
163 static void
164 free_saved_signal_handlers (void)
165 {
166         if (mono_saved_signal_handlers) {
167                 g_hash_table_destroy (mono_saved_signal_handlers);
168                 mono_saved_signal_handlers = NULL;
169         }
170 }
171
172 /*
173  * mono_chain_signal:
174  *
175  *   Call the original signal handler for the signal given by the arguments, which
176  * should be the same as for a signal handler. Returns TRUE if the original handler
177  * was called, false otherwise.
178  */
179 gboolean
180 MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
181 {
182         int signal = MONO_SIG_HANDLER_GET_SIGNO ();
183         struct sigaction *saved_handler = (struct sigaction *)get_saved_signal_handler (signal, FALSE);
184
185         if (saved_handler && saved_handler->sa_handler) {
186                 if (!(saved_handler->sa_flags & SA_SIGINFO)) {
187                         saved_handler->sa_handler (signal);
188                 } else {
189 #ifdef MONO_ARCH_USE_SIGACTION
190                         saved_handler->sa_sigaction (MONO_SIG_HANDLER_PARAMS);
191 #endif /* MONO_ARCH_USE_SIGACTION */
192                 }
193                 return TRUE;
194         }
195         return FALSE;
196 }
197
198 MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
199 {
200         MonoJitInfo *ji = NULL;
201         MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
202         MONO_SIG_HANDLER_GET_CONTEXT;
203
204         if (mono_thread_internal_current ())
205                 ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
206         if (!ji) {
207         if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
208                         return;
209                 mono_handle_native_crash ("SIGABRT", ctx, info);
210         }
211 }
212
213 #if defined(__i386__) || defined(__x86_64__)
214 #define FULL_STAT_PROFILER_BACKTRACE 1
215 #define CURRENT_FRAME_GET_BASE_POINTER(f) (* (gpointer*)(f))
216 #define CURRENT_FRAME_GET_RETURN_ADDRESS(f) (* (((gpointer*)(f)) + 1))
217 #if MONO_ARCH_STACK_GROWS_UP
218 #define IS_BEFORE_ON_STACK <
219 #define IS_AFTER_ON_STACK >
220 #else
221 #define IS_BEFORE_ON_STACK >
222 #define IS_AFTER_ON_STACK <
223 #endif
224 #else
225 #define FULL_STAT_PROFILER_BACKTRACE 0
226 #endif
227
228 #if (defined (USE_POSIX_BACKEND) && defined (SIGRTMIN)) || defined (SIGPROF)
229 #define HAVE_PROFILER_SIGNAL
230 #endif
231
232 #ifdef HAVE_PROFILER_SIGNAL
233
234 static void
235 per_thread_profiler_hit (void *ctx)
236 {
237         int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
238         MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
239
240         if (call_chain_depth == 0) {
241                 mono_profiler_stat_hit ((guchar *)mono_arch_ip_from_context (ctx), ctx);
242         } else {
243                 MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
244                 int current_frame_index = 1;
245                 MonoContext mono_context;
246                 guchar *ips [call_chain_depth + 1];
247
248                 mono_sigctx_to_monoctx (ctx, &mono_context);
249                 ips [0] = (guchar *)MONO_CONTEXT_GET_IP (&mono_context);
250                 
251                 if (jit_tls != NULL) {
252                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
253 #if FULL_STAT_PROFILER_BACKTRACE
254                         guchar *current_frame;
255                         guchar *stack_bottom;
256                         guchar *stack_top;
257                         
258                         stack_bottom = (guchar *)jit_tls->end_of_stack;
259                         stack_top = (guchar *)MONO_CONTEXT_GET_SP (&mono_context);
260                         current_frame = (guchar *)MONO_CONTEXT_GET_BP (&mono_context);
261                         
262                         while ((current_frame_index <= call_chain_depth) &&
263                                         (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
264                                         ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
265                                 ips [current_frame_index] = (guchar *)CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
266                                 current_frame_index ++;
267                                 stack_top = current_frame;
268                                 current_frame = (guchar *)CURRENT_FRAME_GET_BASE_POINTER (current_frame);
269                         }
270 #else
271                                 call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
272 #endif
273                         }
274                         
275                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
276 #if GLIBC_PROFILER_BACKTRACE
277                                 current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
278 #else
279                                 call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
280 #endif
281                         }
282
283                         if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
284                                 MonoDomain *domain = mono_domain_get ();
285                                 if (domain != NULL) {
286                                         MonoLMF *lmf = NULL;
287                                         MonoJitInfo *ji;
288                                         MonoJitInfo res;
289                                         MonoContext new_mono_context;
290                                         int native_offset;
291                                         ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
292                                                         &new_mono_context, NULL, &lmf, &native_offset, NULL);
293                                         while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
294                                                 ips [current_frame_index] = (guchar *)MONO_CONTEXT_GET_IP (&new_mono_context);
295                                                 current_frame_index ++;
296                                                 mono_context = new_mono_context;
297                                                 ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
298                                                                 &new_mono_context, NULL, &lmf, &native_offset, NULL);
299                                         }
300                                 }
301                         }
302                 }
303                 
304                 mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
305         }
306 }
307
308 static MonoNativeThreadId sampling_thread;
309
310 static gint32 profiler_signals_sent;
311 static gint32 profiler_signals_received;
312 static gint32 profiler_signals_accepted;
313 static gint32 profiler_interrupt_signals_received;
314
315 MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler)
316 {
317         int old_errno = errno;
318
319         MONO_SIG_HANDLER_GET_CONTEXT;
320
321         /* See the comment in mono_runtime_shutdown_stat_profiler (). */
322         if (mono_native_thread_id_get () == sampling_thread) {
323                 InterlockedIncrement (&profiler_interrupt_signals_received);
324                 return;
325         }
326
327         InterlockedIncrement (&profiler_signals_received);
328
329         // Did a non-attached or detaching thread get the signal?
330         if (mono_thread_info_get_small_id () == -1 ||
331             !mono_domain_get () ||
332             !mono_tls_get_jit_tls ()) {
333                 errno = old_errno;
334                 return;
335         }
336
337         // See the comment in sampling_thread_func ().
338         InterlockedWrite (&mono_thread_info_current ()->profiler_signal_ack, 1);
339
340         InterlockedIncrement (&profiler_signals_accepted);
341
342         int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
343
344         mono_thread_info_set_is_async_context (TRUE);
345         per_thread_profiler_hit (ctx);
346         mono_thread_info_set_is_async_context (FALSE);
347
348         mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
349
350         errno = old_errno;
351
352         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
353 }
354
355 #endif
356
357 MONO_SIG_HANDLER_FUNC (static, sigquit_signal_handler)
358 {
359         gboolean res;
360
361         /* We use this signal to start the attach agent too */
362         res = mono_attach_start ();
363         if (res)
364                 return;
365
366         mono_threads_request_thread_dump ();
367
368         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
369 }
370
371 MONO_SIG_HANDLER_FUNC (static, sigusr2_signal_handler)
372 {
373         gboolean enabled = mono_trace_is_enabled ();
374
375         mono_trace_enable (!enabled);
376
377         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
378 }
379
380 static void
381 add_signal_handler (int signo, gpointer handler, int flags)
382 {
383         struct sigaction sa;
384         struct sigaction previous_sa;
385
386 #ifdef MONO_ARCH_USE_SIGACTION
387         sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
388         sigemptyset (&sa.sa_mask);
389         sa.sa_flags = SA_SIGINFO | flags;
390 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
391
392 /*Apple likes to deliver SIGBUS for *0 */
393 #ifdef PLATFORM_MACOSX
394         if (signo == SIGSEGV || signo == SIGBUS) {
395 #else
396         if (signo == SIGSEGV) {
397 #endif
398                 sa.sa_flags |= SA_ONSTACK;
399
400                 /* 
401                  * libgc will crash when trying to do stack marking for threads which are on
402                  * an altstack, so delay the suspend signal after the signal handler has
403                  * executed.
404                  */
405                 if (mono_gc_get_suspend_signal () != -1)
406                         sigaddset (&sa.sa_mask, mono_gc_get_suspend_signal ());
407         }
408 #endif
409         if (signo == SIGSEGV) {
410                 /* 
411                  * Delay abort signals while handling SIGSEGVs since they could go unnoticed.
412                  */
413                 sigset_t block_mask;
414      
415                 sigemptyset (&block_mask);
416         }
417 #else
418         sa.sa_handler = handler;
419         sigemptyset (&sa.sa_mask);
420         sa.sa_flags = flags;
421 #endif
422         g_assert (sigaction (signo, &sa, &previous_sa) != -1);
423
424         /* if there was already a handler in place for this signal, store it */
425         if (! (previous_sa.sa_flags & SA_SIGINFO) &&
426                         (SIG_DFL == previous_sa.sa_handler)) { 
427                 /* it there is no sa_sigaction function and the sa_handler is default, we can safely ignore this */
428         } else {
429                 if (mono_do_signal_chaining)
430                         save_old_signal_handler (signo, &previous_sa);
431         }
432 }
433
434 static void
435 remove_signal_handler (int signo)
436 {
437         struct sigaction sa;
438         struct sigaction *saved_action = get_saved_signal_handler (signo, TRUE);
439
440         if (!saved_action) {
441                 sa.sa_handler = SIG_DFL;
442                 sigemptyset (&sa.sa_mask);
443                 sa.sa_flags = 0;
444
445                 sigaction (signo, &sa, NULL);
446         } else {
447                 g_assert (sigaction (signo, saved_action, NULL) != -1);
448         }
449 }
450
451 void
452 mono_runtime_posix_install_handlers (void)
453 {
454
455         sigset_t signal_set;
456
457         if (mini_get_debug_options ()->handle_sigint)
458                 add_signal_handler (SIGINT, mono_sigint_signal_handler, SA_RESTART);
459
460         add_signal_handler (SIGFPE, mono_sigfpe_signal_handler, 0);
461         add_signal_handler (SIGQUIT, sigquit_signal_handler, SA_RESTART);
462         add_signal_handler (SIGILL, mono_sigill_signal_handler, 0);
463         add_signal_handler (SIGBUS, mono_sigsegv_signal_handler, 0);
464         if (mono_jit_trace_calls != NULL)
465                 add_signal_handler (SIGUSR2, sigusr2_signal_handler, SA_RESTART);
466
467         /* it seems to have become a common bug for some programs that run as parents
468          * of many processes to block signal delivery for real time signals.
469          * We try to detect and work around their breakage here.
470          */
471         sigemptyset (&signal_set);
472         if (mono_gc_get_suspend_signal () != -1)
473                 sigaddset (&signal_set, mono_gc_get_suspend_signal ());
474         if (mono_gc_get_restart_signal () != -1)
475                 sigaddset (&signal_set, mono_gc_get_restart_signal ());
476         sigaddset (&signal_set, SIGCHLD);
477         sigprocmask (SIG_UNBLOCK, &signal_set, NULL);
478
479         signal (SIGPIPE, SIG_IGN);
480
481         add_signal_handler (SIGABRT, sigabrt_signal_handler, 0);
482
483         /* catch SIGSEGV */
484         add_signal_handler (SIGSEGV, mono_sigsegv_signal_handler, 0);
485 }
486
487 #ifndef PLATFORM_MACOSX
488 void
489 mono_runtime_install_handlers (void)
490 {
491         mono_runtime_posix_install_handlers ();
492 }
493 #endif
494
495 void
496 mono_runtime_cleanup_handlers (void)
497 {
498         if (mini_get_debug_options ()->handle_sigint)
499                 remove_signal_handler (SIGINT);
500
501         remove_signal_handler (SIGFPE);
502         remove_signal_handler (SIGQUIT);
503         remove_signal_handler (SIGILL);
504         remove_signal_handler (SIGBUS);
505         if (mono_jit_trace_calls != NULL)
506                 remove_signal_handler (SIGUSR2);
507
508         remove_signal_handler (SIGABRT);
509
510         remove_signal_handler (SIGSEGV);
511
512         free_saved_signal_handlers ();
513 }
514
515 #ifdef HAVE_PROFILER_SIGNAL
516
517 static volatile gint32 sampling_thread_running;
518
519 #ifdef PLATFORM_MACOSX
520
521 static clock_serv_t sampling_clock_service;
522
523 static void
524 clock_init (void)
525 {
526         kern_return_t ret;
527
528         do {
529                 ret = host_get_clock_service (mach_host_self (), SYSTEM_CLOCK, &sampling_clock_service);
530         } while (ret == KERN_ABORTED);
531
532         if (ret != KERN_SUCCESS)
533                 g_error ("%s: host_get_clock_service () returned %d", __func__, ret);
534 }
535
536 static void
537 clock_cleanup (void)
538 {
539         kern_return_t ret;
540
541         do {
542                 ret = mach_port_deallocate (mach_task_self (), sampling_clock_service);
543         } while (ret == KERN_ABORTED);
544
545         if (ret != KERN_SUCCESS)
546                 g_error ("%s: mach_port_deallocate () returned %d", __func__, ret);
547 }
548
549 static guint64
550 clock_get_time_ns (void)
551 {
552         kern_return_t ret;
553         mach_timespec_t mach_ts;
554
555         do {
556                 ret = clock_get_time (sampling_clock_service, &mach_ts);
557         } while (ret == KERN_ABORTED);
558
559         if (ret != KERN_SUCCESS)
560                 g_error ("%s: clock_get_time () returned %d", __func__, ret);
561
562         return ((guint64) mach_ts.tv_sec * 1000000000) + (guint64) mach_ts.tv_nsec;
563 }
564
565 static void
566 clock_sleep_ns_abs (guint64 ns_abs)
567 {
568         kern_return_t ret;
569         mach_timespec_t then, remain_unused;
570
571         then.tv_sec = ns_abs / 1000000000;
572         then.tv_nsec = ns_abs % 1000000000;
573
574         do {
575                 ret = clock_sleep (sampling_clock_service, TIME_ABSOLUTE, then, &remain_unused);
576
577                 if (ret != KERN_SUCCESS && ret != KERN_ABORTED)
578                         g_error ("%s: clock_sleep () returned %d", __func__, ret);
579         } while (ret == KERN_ABORTED && InterlockedRead (&sampling_thread_running));
580 }
581
582 #else
583
584 clockid_t sampling_posix_clock;
585
586 static void
587 clock_init (void)
588 {
589         switch (mono_profiler_get_sampling_mode ()) {
590         case MONO_PROFILER_STAT_MODE_PROCESS: {
591         /*
592          * If we don't have clock_nanosleep (), measuring the process time
593          * makes very little sense as we can only use nanosleep () to sleep on
594          * real time.
595          */
596 #ifdef HAVE_CLOCK_NANOSLEEP
597                 struct timespec ts = { 0 };
598
599                 /*
600                  * Some systems (e.g. Windows Subsystem for Linux) declare the
601                  * CLOCK_PROCESS_CPUTIME_ID clock but don't actually support it. For
602                  * those systems, we fall back to CLOCK_MONOTONIC if we get EINVAL.
603                  */
604                 if (clock_nanosleep (CLOCK_PROCESS_CPUTIME_ID, TIMER_ABSTIME, &ts, NULL) != EINVAL) {
605                         sampling_posix_clock = CLOCK_PROCESS_CPUTIME_ID;
606                         break;
607                 }
608 #endif
609
610                 // fallthrough
611         }
612         case MONO_PROFILER_STAT_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break;
613         default: g_assert_not_reached (); break;
614         }
615 }
616
617 static void
618 clock_cleanup (void)
619 {
620 }
621
622 static guint64
623 clock_get_time_ns (void)
624 {
625         struct timespec ts;
626
627         if (clock_gettime (sampling_posix_clock, &ts) == -1)
628                 g_error ("%s: clock_gettime () returned -1, errno = %d", __func__, errno);
629
630         return ((guint64) ts.tv_sec * 1000000000) + (guint64) ts.tv_nsec;
631 }
632
633 static void
634 clock_sleep_ns_abs (guint64 ns_abs)
635 {
636 #ifdef HAVE_CLOCK_NANOSLEEP
637         int ret;
638         struct timespec then;
639
640         then.tv_sec = ns_abs / 1000000000;
641         then.tv_nsec = ns_abs % 1000000000;
642
643         do {
644                 ret = clock_nanosleep (sampling_posix_clock, TIMER_ABSTIME, &then, NULL);
645
646                 if (ret != 0 && ret != EINTR)
647                         g_error ("%s: clock_nanosleep () returned %d", __func__, ret);
648         } while (ret == EINTR && InterlockedRead (&sampling_thread_running));
649 #else
650         int ret;
651         gint64 diff;
652         struct timespec req;
653
654         /*
655          * What follows is a crude attempt at emulating clock_nanosleep () on OSs
656          * which don't provide it (e.g. FreeBSD).
657          *
658          * The problem with nanosleep () is that if it is interrupted by a signal,
659          * time will drift as a result of having to restart the call after the
660          * signal handler has finished. For this reason, we avoid using the rem
661          * argument of nanosleep (). Instead, before every nanosleep () call, we
662          * check if enough time has passed to satisfy the sleep request. If yes, we
663          * simply return. If not, we calculate the difference and do another sleep.
664          *
665          * This should reduce the amount of drift that happens because we account
666          * for the time spent executing the signal handler, which nanosleep () is
667          * not guaranteed to do for the rem argument.
668          *
669          * The downside to this approach is that it is slightly expensive: We have
670          * to make an extra system call to retrieve the current time whenever we're
671          * going to restart a nanosleep () call. This is unlikely to be a problem
672          * in practice since the sampling thread won't be receiving many signals in
673          * the first place (it's a tools thread, so no STW), and because typical
674          * sleep periods for the thread are many orders of magnitude bigger than
675          * the time it takes to actually perform that system call (just a few
676          * nanoseconds).
677          */
678         do {
679                 diff = (gint64) ns_abs - (gint64) clock_get_time_ns ();
680
681                 if (diff <= 0)
682                         break;
683
684                 req.tv_sec = diff / 1000000000;
685                 req.tv_nsec = diff % 1000000000;
686
687                 if ((ret = nanosleep (&req, NULL)) == -1 && errno != EINTR)
688                         g_error ("%s: nanosleep () returned -1, errno = %d", __func__, errno);
689         } while (ret == -1 && InterlockedRead (&sampling_thread_running));
690 #endif
691 }
692
693 #endif
694
695 static int profiler_signal;
696 static volatile gint32 sampling_thread_exiting;
697
698 static mono_native_thread_return_t
699 sampling_thread_func (void *data)
700 {
701         mono_threads_attach_tools_thread ();
702         mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler sampler");
703
704         gint64 rate = 1000000000 / mono_profiler_get_sampling_rate ();
705
706         int old_policy;
707         struct sched_param old_sched;
708         pthread_getschedparam (pthread_self (), &old_policy, &old_sched);
709
710         /*
711          * Attempt to switch the thread to real time scheduling. This will not
712          * necessarily work on all OSs; for example, most Linux systems will give
713          * us EPERM here unless configured to allow this.
714          *
715          * TODO: This does not work on Mac (and maybe some other OSs). On Mac, we
716          * have to use the Mach thread policy routines to switch to real-time
717          * scheduling. This is quite tricky as we need to specify how often we'll
718          * be doing work (easy), the normal processing time needed (also easy),
719          * and the maximum amount of processing time needed (hard). This is
720          * further complicated by the fact that if we misbehave and take too long
721          * to do our work, the kernel may knock us back down to the normal thread
722          * scheduling policy without telling us.
723          */
724         struct sched_param sched = { .sched_priority = sched_get_priority_max (SCHED_FIFO) };
725         pthread_setschedparam (pthread_self (), SCHED_FIFO, &sched);
726
727         clock_init ();
728
729         guint64 sleep = clock_get_time_ns ();
730
731         while (InterlockedRead (&sampling_thread_running)) {
732                 sleep += rate;
733
734                 FOREACH_THREAD_SAFE (info) {
735                         /* info should never be this thread as we're a tools thread. */
736                         g_assert (mono_thread_info_get_tid (info) != mono_native_thread_id_get ());
737
738                         /*
739                          * Require an ack for the last sampling signal sent to the thread
740                          * so that we don't overflow the signal queue, leading to all sorts
741                          * of problems (e.g. GC STW failing).
742                          */
743                         if (profiler_signal != SIGPROF && !InterlockedCompareExchange (&info->profiler_signal_ack, 0, 1))
744                                 continue;
745
746                         mono_threads_pthread_kill (info, profiler_signal);
747                         InterlockedIncrement (&profiler_signals_sent);
748                 } FOREACH_THREAD_SAFE_END
749
750                 clock_sleep_ns_abs (sleep);
751         }
752
753         InterlockedWrite (&sampling_thread_exiting, 1);
754
755         clock_cleanup ();
756
757         pthread_setschedparam (pthread_self (), old_policy, &old_sched);
758
759         mono_thread_info_detach ();
760
761         return NULL;
762 }
763
764 void
765 mono_runtime_shutdown_stat_profiler (void)
766 {
767         InterlockedWrite (&sampling_thread_running, 0);
768
769 #ifndef PLATFORM_MACOSX
770         /*
771          * There is a slight problem when we're using CLOCK_PROCESS_CPUTIME_ID: If
772          * we're shutting down and there's largely no activity in the process other
773          * than waiting for the sampler thread to shut down, it can take upwards of
774          * 20 seconds (depending on a lot of factors) for us to shut down because
775          * the sleep progresses very slowly as a result of the low CPU activity.
776          *
777          * We fix this by repeatedly sending the profiler signal to the sampler
778          * thread in order to interrupt the sleep. clock_sleep_ns_abs () will check
779          * sampling_thread_running upon an interrupt and return immediately if it's
780          * zero. profiler_signal_handler () has a special case to ignore the signal
781          * for the sampler thread.
782          */
783         MonoThreadInfo *info;
784
785         // Did it shut down already?
786         if ((info = mono_thread_info_lookup (sampling_thread))) {
787                 while (!InterlockedRead (&sampling_thread_exiting)) {
788                         mono_threads_pthread_kill (info, profiler_signal);
789                         mono_thread_info_usleep (10 * 1000 /* 10ms */);
790                 }
791
792                 // Make sure info can be freed.
793                 mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
794         }
795 #endif
796
797         mono_native_thread_join (sampling_thread);
798
799         /*
800          * We can't safely remove the signal handler because we have no guarantee
801          * that all pending signals have been delivered at this point. This should
802          * not really be a problem anyway.
803          */
804         //remove_signal_handler (profiler_signal);
805 }
806
807 void
808 mono_runtime_setup_stat_profiler (void)
809 {
810         /*
811          * Use a real-time signal when possible. This gives us roughly a 99% signal
812          * delivery rate in all cases. On the other hand, using a regular signal
813          * tends to result in awful delivery rates when the application is heavily
814          * loaded.
815          *
816          * We avoid real-time signals on Android as they're super broken in certain
817          * API levels (too small sigset_t, nonsensical SIGRTMIN/SIGRTMAX values,
818          * etc).
819          *
820          * TODO: On Mac, we should explore using the Mach thread suspend/resume
821          * functions and doing the stack walk from the sampling thread. This would
822          * get us a 100% sampling rate. However, this may interfere with the GC's
823          * STW logic. Could perhaps be solved by taking the suspend lock.
824          */
825 #if defined (USE_POSIX_BACKEND) && defined (SIGRTMIN) && !defined (PLATFORM_ANDROID)
826         /* Just take the first real-time signal we can get. */
827         profiler_signal = mono_threads_suspend_search_alternative_signal ();
828 #else
829         profiler_signal = SIGPROF;
830 #endif
831
832         add_signal_handler (profiler_signal, profiler_signal_handler, SA_RESTART);
833
834         mono_counters_register ("Sampling signals sent", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_sent);
835         mono_counters_register ("Sampling signals received", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_received);
836         mono_counters_register ("Sampling signals accepted", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_signals_accepted);
837         mono_counters_register ("Shutdown signals received", MONO_COUNTER_UINT | MONO_COUNTER_PROFILER | MONO_COUNTER_MONOTONIC, &profiler_interrupt_signals_received);
838
839         InterlockedWrite (&sampling_thread_running, 1);
840         mono_native_thread_create (&sampling_thread, sampling_thread_func, NULL);
841 }
842
843 #else
844
845 void
846 mono_runtime_shutdown_stat_profiler (void)
847 {
848 }
849
850 void
851 mono_runtime_setup_stat_profiler (void)
852 {
853 }
854
855 #endif
856
857 #endif /* defined(HOST_WATCHOS) */
858
859 static gboolean
860 native_stack_with_gdb (pid_t crashed_pid, const char **argv, FILE *commands, char* commands_filename)
861 {
862         gchar *gdb;
863
864         gdb = g_find_program_in_path ("gdb");
865         if (!gdb)
866                 return FALSE;
867
868         argv [0] = gdb;
869         argv [1] = "-batch";
870         argv [2] = "-x";
871         argv [3] = commands_filename;
872         argv [4] = "-nx";
873
874         fprintf (commands, "attach %ld\n", (long) crashed_pid);
875         fprintf (commands, "info threads\n");
876         fprintf (commands, "thread apply all bt\n");
877
878         return TRUE;
879 }
880
881
882 static gboolean
883 native_stack_with_lldb (pid_t crashed_pid, const char **argv, FILE *commands, char* commands_filename)
884 {
885         gchar *lldb;
886
887         lldb = g_find_program_in_path ("lldb");
888         if (!lldb)
889                 return FALSE;
890
891         argv [0] = lldb;
892         argv [1] = "--batch";
893         argv [2] = "--source";
894         argv [3] = commands_filename;
895         argv [4] = "--no-lldbinit";
896
897         fprintf (commands, "process attach --pid %ld\n", (long) crashed_pid);
898         fprintf (commands, "thread list\n");
899         fprintf (commands, "thread backtrace all\n");
900         fprintf (commands, "detach\n");
901         fprintf (commands, "quit\n");
902
903         return TRUE;
904 }
905
906 void
907 mono_gdb_render_native_backtraces (pid_t crashed_pid)
908 {
909 #ifdef HAVE_EXECV
910         const char *argv [10];
911         FILE *commands;
912         char commands_filename [] = "/tmp/mono-gdb-commands.XXXXXX";
913
914         if (mkstemp (commands_filename) == -1)
915                 return;
916
917         commands = fopen (commands_filename, "w");
918         if (!commands) {
919                 unlink (commands_filename);
920                 return;
921         }
922
923         memset (argv, 0, sizeof (char*) * 10);
924
925 #if defined(PLATFORM_MACOSX)
926         if (native_stack_with_lldb (crashed_pid, argv, commands, commands_filename))
927                 goto exec;
928 #endif
929
930         if (native_stack_with_gdb (crashed_pid, argv, commands, commands_filename))
931                 goto exec;
932
933 #if !defined(PLATFORM_MACOSX)
934         if (native_stack_with_lldb (crashed_pid, argv, commands, commands_filename))
935                 goto exec;
936 #endif
937
938         fprintf (stderr, "mono_gdb_render_native_backtraces not supported on this platform, unable to find gdb or lldb\n");
939
940         fclose (commands);
941         unlink (commands_filename);
942         return;
943
944 exec:
945         fclose (commands);
946         execv (argv [0], (char**)argv);
947
948         _exit (-1);
949 #else
950         fprintf (stderr, "mono_gdb_render_native_backtraces not supported on this platform\n");
951 #endif // HAVE_EXECV
952 }
953
954 #if !defined (__MACH__)
955
956 gboolean
957 mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info)
958 {
959         g_error ("Posix systems don't support mono_thread_state_init_from_handle");
960         return FALSE;
961 }
962
963 #endif