From f03bce6a77ff5c7885a3b200fe879210299194bb Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 4 Dec 2014 11:00:22 +0100 Subject: erts: Add support for thread names --- erts/emulator/sys/unix/sys.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'erts/emulator/sys/unix') diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index 5de0c281c4..3320d3e314 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -1327,6 +1327,7 @@ static int spawn_init() thr_opts.detached = 0; thr_opts.suggested_stack_size = 0; /* Smallest possible */ + thr_opts.name = "child_waiter"; #endif sys_sigset(SIGPIPE, SIG_IGN); /* Ignore - we'll handle the write failure */ @@ -3230,6 +3231,7 @@ init_smp_sig_notify(void) { erts_smp_thr_opts_t thr_opts = ERTS_SMP_THR_OPTS_DEFAULT_INITER; thr_opts.detached = 1; + thr_opts.name = "sys_sig_dispatcher"; if (pipe(sig_notify_fds) < 0) { erl_exit(ERTS_ABORT_EXIT, -- cgit v1.2.3 From d6d1ef4787951070dd152daf44eff2003b7f2ed2 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 9 Dec 2014 08:47:49 +0100 Subject: erts: Remove usage of QUANTIFY signal --- erts/emulator/sys/unix/sys.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'erts/emulator/sys/unix') diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index 3320d3e314..81ed5626c2 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -894,21 +894,6 @@ static RETSIGTYPE user_signal1(int signum) #endif } -#ifdef QUANTIFY -#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL)) -static RETSIGTYPE user_signal2(void) -#else -static RETSIGTYPE user_signal2(int signum) -#endif -{ -#ifdef ERTS_SMP - smp_sig_notify('2'); -#else - quantify_save_data(); -#endif -} -#endif - #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */ static void @@ -960,9 +945,6 @@ void init_break_handler(void) sys_sigset(SIGINT, request_break); #ifndef ETHR_UNUSABLE_SIGUSRX sys_sigset(SIGUSR1, user_signal1); -#ifdef QUANTIFY - sys_sigset(SIGUSR2, user_signal2); -#endif #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */ sys_sigset(SIGQUIT, do_quit); } @@ -3207,13 +3189,6 @@ signal_dispatcher_thread_func(void *unused) case '1': /* SIGUSR1 */ sigusr1_exit(); break; -#ifdef QUANTIFY - case '2': /* SIGUSR2 */ - quantify_save_data(); /* Might take a substantial amount of - time, but this is a test/debug - build */ - break; -#endif default: erl_exit(ERTS_ABORT_EXIT, "signal-dispatcher thread received unknown " -- cgit v1.2.3 From b8a2313263d0f120dacbe82ced5c99545bbd15a3 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 4 Dec 2014 11:04:23 +0100 Subject: erts: Introduce thread suspend functions These functions allow any thread to suspend any other thread immediately and then resume all threads. This is useful when doing a crash dump in order to get a more accurate picture of what state the system is in. --- erts/emulator/sys/unix/sys.c | 69 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 4 deletions(-) (limited to 'erts/emulator/sys/unix') diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index 81ed5626c2..841f0c7575 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -216,6 +216,9 @@ static erts_smp_atomic_t sys_misc_mem_sz; #if defined(ERTS_SMP) static void smp_sig_notify(char c); static int sig_notify_fds[2] = {-1, -1}; + +static int sig_suspend_fds[2] = {-1, -1}; +#define ERTS_SYS_SUSPEND_SIGNAL SIGUSR2 #elif defined(USE_THREADS) static int async_fd[2]; #endif @@ -789,6 +792,9 @@ prepare_crash_dump(int secs) /* We don't want to close the signal notification pipe... */ if (i == sig_notify_fds[0] || i == sig_notify_fds[1]) continue; + /* We don't want to close the signal syspend pipe... */ + if (i == sig_suspend_fds[0] || i == sig_suspend_fds[1]) + continue; #elif defined(USE_THREADS) /* We don't want to close the async notification pipe... */ if (i == async_fd[0] || i == async_fd[1]) @@ -877,9 +883,23 @@ sigusr1_exit(void) #ifdef ETHR_UNUSABLE_SIGUSRX #warning "Unusable SIGUSR1 & SIGUSR2. Disabling use of these signals" -#endif -#ifndef ETHR_UNUSABLE_SIGUSRX +#else + +#ifdef ERTS_SMP +void +sys_thr_suspend(erts_tid_t tid) { + erts_thr_kill(tid, ERTS_SYS_SUSPEND_SIGNAL); +} + +void +sys_thr_resume(erts_tid_t tid) { + int i = 0, res; + do { + res = write(sig_suspend_fds[1],&i,sizeof(i)); + } while (res < 0 && errno == EAGAIN); +} +#endif #if (defined(SIG_SIGSET) || defined(SIG_SIGNAL)) static RETSIGTYPE user_signal1(void) @@ -894,6 +914,21 @@ static RETSIGTYPE user_signal1(int signum) #endif } +#ifdef ERTS_SMP +#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL)) +static RETSIGTYPE suspend_signal(void) +#else +static RETSIGTYPE suspend_signal(int signum) +#endif +{ + int res; + int buf[1]; + do { + res = read(sig_suspend_fds[0], buf, sizeof(int)); + } while (res < 0 && errno == EINTR); +} +#endif /* #ifdef ERTS_SMP */ + #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */ static void @@ -944,7 +979,10 @@ void init_break_handler(void) { sys_sigset(SIGINT, request_break); #ifndef ETHR_UNUSABLE_SIGUSRX - sys_sigset(SIGUSR1, user_signal1); + sys_signal(SIGUSR1, user_signal1); +#ifdef ERTS_SMP + sys_signal(ERTS_SYS_SUSPEND_SIGNAL, suspend_signal); +#endif /* #ifdef ERTS_SMP */ #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */ sys_sigset(SIGQUIT, do_quit); } @@ -963,8 +1001,13 @@ static void block_signals(void) sys_sigblock(SIGINT); #ifndef ETHR_UNUSABLE_SIGUSRX sys_sigblock(SIGUSR1); +#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */ +#endif /* #ifndef ERTS_SMP */ + +#if defined(ERTS_SMP) && !defined(ETHR_UNUSABLE_SIGUSRX) + sys_sigblock(ERTS_SYS_SUSPEND_SIGNAL); #endif -#endif + } static void unblock_signals(void) @@ -978,8 +1021,14 @@ static void unblock_signals(void) #ifndef ETHR_UNUSABLE_SIGUSRX sys_sigrelease(SIGUSR1); #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */ +#endif /* #ifndef ERTS_SMP */ + +#if defined(ERTS_SMP) && !defined(ETHR_UNUSABLE_SIGUSRX) + sys_sigrelease(ERTS_SYS_SUSPEND_SIGNAL); #endif + } + /************************** Time stuff **************************/ #ifdef HAVE_GETHRTIME #ifdef GETHRTIME_WITH_CLOCK_GETTIME @@ -3221,6 +3270,17 @@ init_smp_sig_notify(void) NULL, &thr_opts); } + +static void +init_smp_sig_suspend(void) { + if (pipe(sig_suspend_fds) < 0) { + erl_exit(ERTS_ABORT_EXIT, + "Failed to create sig_suspend pipe: %s (%d)\n", + erl_errno_id(errno), + errno); + } +} + #ifdef __DARWIN__ int erts_darwin_main_thread_pipe[2]; @@ -3371,6 +3431,7 @@ erl_sys_args(int* argc, char** argv) #ifdef ERTS_SMP init_smp_sig_notify(); + init_smp_sig_suspend(); #endif /* Handled arguments have been marked with NULL. Slide arguments -- cgit v1.2.3 From e2a600341324d2ce3689119f8fd61b248702d79f Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 5 Dec 2014 10:14:51 +0100 Subject: erts: Rename sys_sigset to sys_signal Also removed old legacy fallback that is no longer used --- erts/emulator/sys/unix/erl_unix_sys.h | 9 ++--- erts/emulator/sys/unix/sys.c | 65 +++++------------------------------ erts/emulator/sys/unix/sys_float.c | 4 +-- 3 files changed, 12 insertions(+), 66 deletions(-) (limited to 'erts/emulator/sys/unix') diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h index 26ed2fb558..bc55fab8fb 100644 --- a/erts/emulator/sys/unix/erl_unix_sys.h +++ b/erts/emulator/sys/unix/erl_unix_sys.h @@ -211,13 +211,8 @@ int sys_stop_hrvtime(void); #define SYS_CLOCK_RESOLUTION 1 /* These are defined in sys.c */ -#if defined(SIG_SIGSET) /* Old SysV */ -RETSIGTYPE (*sys_sigset())(); -#elif defined(SIG_SIGNAL) /* Old BSD */ -RETSIGTYPE (*sys_sigset())(); -#else -RETSIGTYPE (*sys_sigset(int, RETSIGTYPE (*func)(int)))(int); -#endif +typedef void (*SIGFUNC)(int); +extern SIGFUNC sys_signal(int, SIGFUNC); extern void sys_sigrelease(int); extern void sys_sigblock(int); extern void sys_stop_cat(void); diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index 841f0c7575..74d67cbd57 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -649,39 +649,7 @@ erl_sys_init(void) /* signal handling */ -#ifdef SIG_SIGSET /* Old SysV */ -RETSIGTYPE (*sys_sigset(sig, func))() -int sig; -RETSIGTYPE (*func)(); -{ - return(sigset(sig, func)); -} -void sys_sigblock(int sig) -{ - sighold(sig); -} -void sys_sigrelease(int sig) -{ - sigrelse(sig); -} -#else /* !SIG_SIGSET */ -#ifdef SIG_SIGNAL /* Old BSD */ -RETSIGTYPE (*sys_sigset(sig, func))(int, int) -int sig; -RETSIGTYPE (*func)(); -{ - return(signal(sig, func)); -} -sys_sigblock(int sig) -{ - sigblock(sig); -} -sys_sigrelease(int sig) -{ - sigsetmask(sigblock(0) & ~sigmask(sig)); -} -#else /* !SIG_SIGNAL */ /* The True Way - POSIX!:-) */ -RETSIGTYPE (*sys_sigset(int sig, RETSIGTYPE (*func)(int)))(int) +SIGFUNC sys_signal(int sig, SIGFUNC func) { struct sigaction act, oact; @@ -714,23 +682,6 @@ void sys_sigrelease(int sig) sigaddset(&mask, sig); sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)NULL); } -#endif /* !SIG_SIGNAL */ -#endif /* !SIG_SIGSET */ - -#if (0) /* not used? -- gordon */ -static void (*break_func)(); -static RETSIGTYPE break_handler(int sig) -{ -#ifdef QNX - /* Turn off SIGCHLD during break processing */ - sys_sigblock(SIGCHLD); -#endif - (*break_func)(); -#ifdef QNX - sys_sigrelease(SIGCHLD); -#endif -} -#endif /* 0 */ static ERTS_INLINE int prepare_crash_dump(int secs) @@ -952,9 +903,9 @@ static RETSIGTYPE do_quit(int signum) /* Disable break */ void erts_set_ignore_break(void) { - sys_sigset(SIGINT, SIG_IGN); - sys_sigset(SIGQUIT, SIG_IGN); - sys_sigset(SIGTSTP, SIG_IGN); + sys_signal(SIGINT, SIG_IGN); + sys_signal(SIGQUIT, SIG_IGN); + sys_signal(SIGTSTP, SIG_IGN); } /* Don't use ctrl-c for break handler but let it be @@ -977,14 +928,14 @@ void erts_replace_intr(void) { void init_break_handler(void) { - sys_sigset(SIGINT, request_break); + sys_signal(SIGINT, request_break); #ifndef ETHR_UNUSABLE_SIGUSRX sys_signal(SIGUSR1, user_signal1); #ifdef ERTS_SMP sys_signal(ERTS_SYS_SUSPEND_SIGNAL, suspend_signal); #endif /* #ifdef ERTS_SMP */ #endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */ - sys_sigset(SIGQUIT, do_quit); + sys_signal(SIGQUIT, do_quit); } int sys_max_files(void) @@ -1361,7 +1312,7 @@ static int spawn_init() thr_opts.name = "child_waiter"; #endif - sys_sigset(SIGPIPE, SIG_IGN); /* Ignore - we'll handle the write failure */ + sys_signal(SIGPIPE, SIG_IGN); /* Ignore - we'll handle the write failure */ driver_data = (struct driver_data *) erts_alloc(ERTS_ALC_T_DRV_TAB, max_files * sizeof(struct driver_data)); erts_smp_atomic_add_nob(&sys_misc_mem_sz, @@ -1374,7 +1325,7 @@ static int spawn_init() sys_sigblock(SIGCHLD); #endif - sys_sigset(SIGCHLD, onchld); /* Reap children */ + sys_signal(SIGCHLD, onchld); /* Reap children */ #if CHLDWTHR erts_thr_create(&child_waiter_tid, child_waiter, NULL, &thr_opts); diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c index cafeab547e..2ffa649767 100644 --- a/erts/emulator/sys/unix/sys_float.c +++ b/erts/emulator/sys/unix/sys_float.c @@ -32,7 +32,7 @@ void erts_sys_init_float(void) { # ifdef SIGFPE - sys_sigset(SIGFPE, SIG_IGN); /* Ignore so we can test for NaN and Inf */ + sys_signal(SIGFPE, SIG_IGN); /* Ignore so we can test for NaN and Inf */ # endif } @@ -667,7 +667,7 @@ static void fpe_sig_handler(int sig) static void erts_thread_catch_fp_exceptions(void) { - sys_sigset(SIGFPE, fpe_sig_handler); + sys_signal(SIGFPE, fpe_sig_handler); unmask_fpe(); } -- cgit v1.2.3 From ffd0153e6dffcc29cf79d0191860047dba0438bb Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 4 Dec 2014 11:09:06 +0100 Subject: erts: Improve crash dumps This commit improves crash dumps in several ways: * Suspends schedulers to get a current snapshot * Dumps information about scheduler * Dumps stack trace of current running process (including Garbing processes) --- erts/emulator/sys/unix/erl_unix_sys.h | 26 +++++++++++++++++++++++++- erts/emulator/sys/unix/sys.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) (limited to 'erts/emulator/sys/unix') diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h index bc55fab8fb..1932e97742 100644 --- a/erts/emulator/sys/unix/erl_unix_sys.h +++ b/erts/emulator/sys/unix/erl_unix_sys.h @@ -45,7 +45,7 @@ #include #include "erl_errno.h" #include - +#include #if HAVE_SYS_SOCKETIO_H # include @@ -349,4 +349,28 @@ extern int exit_async(void); #define ERTS_EXIT_AFTER_DUMP _exit +#if !defined(__APPLE__) && !defined(__MACH__) +/* Some OS X versions do not allow (ab)using signal handlers like this */ +#define ERTS_HAVE_TRY_CATCH 1 + +/* We try to simulate a try catch in C with the help of signal handlers. + * Only use this as a very last resort, as it is not very portable and + * quite unstable. It is also not thread safe, so make sure that only + * one thread can call this at a time! + */ +extern void erts_sys_sigsegv_handler(int); +extern jmp_buf erts_sys_sigsegv_jmp; +#define ERTS_SYS_TRY_CATCH(EXPR,CATCH) \ + do { \ + SIGFUNC prev_handler = sys_signal(SIGSEGV, \ + erts_sys_sigsegv_handler); \ + if (!setjmp(erts_sys_sigsegv_jmp)) { \ + EXPR; \ + } else { \ + CATCH; \ + } \ + sys_signal(SIGSEGV,prev_handler); \ + } while(0) +#endif + #endif /* #ifndef _ERL_UNIX_SYS_H */ diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index 74d67cbd57..57f9fbef53 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -223,6 +223,8 @@ static int sig_suspend_fds[2] = {-1, -1}; static int async_fd[2]; #endif +jmp_buf erts_sys_sigsegv_jmp; + #if CHLDWTHR || defined(ERTS_SMP) erts_mtx_t chld_stat_mtx; #endif @@ -683,6 +685,35 @@ void sys_sigrelease(int sig) sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)NULL); } +void erts_sys_sigsegv_handler(int signo) { + if (signo == SIGSEGV) { + longjmp(erts_sys_sigsegv_jmp, 1); + } +} + +/* + * Function returns 1 if we can read from all values in between + * start and stop. + */ +int +erts_sys_is_area_readable(char *start, char *stop) { + int fds[2]; + if (!pipe(fds)) { + /* We let write try to figure out if the pointers are readable */ + int res = write(fds[1], start, (char*)stop - (char*)start); + if (res == -1) { + close(fds[0]); + close(fds[1]); + return 0; + } + close(fds[0]); + close(fds[1]); + return 1; + } + return 0; + +} + static ERTS_INLINE int prepare_crash_dump(int secs) { -- cgit v1.2.3 From bd4b900c09308a6c3ab41e3a2070cb90410ee01d Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 12 Dec 2014 15:13:31 +0100 Subject: erts: Make main thread safe from pipe closed event --- erts/emulator/sys/unix/sys.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'erts/emulator/sys/unix') diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index 57f9fbef53..e1a932fdda 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -3290,9 +3290,11 @@ erts_sys_main_thread(void) #endif smp_sig_notify(0); /* Notify initialized */ - while (1) { - /* Wait for a signal to arrive... */ + + /* Wait for a signal to arrive... */ + #ifdef __DARWIN__ + while (1) { /* * The wx driver needs to be able to steal the main thread for Cocoa to * work properly. @@ -3307,12 +3309,24 @@ erts_sys_main_thread(void) void* (*func)(void*); void* arg; void *resp; - read(erts_darwin_main_thread_pipe[0],&func,sizeof(void* (*)(void*))); - read(erts_darwin_main_thread_pipe[0],&arg, sizeof(void*)); + res = read(erts_darwin_main_thread_pipe[0],&func,sizeof(void* (*)(void*))); + if (res != sizeof(void* (*)(void*))) + break; + res = read(erts_darwin_main_thread_pipe[0],&arg,sizeof(void*)); + if (res != sizeof(void*)) + break; resp = (*func)(arg); write(erts_darwin_main_thread_result_pipe[1],&resp,sizeof(void *)); } -#else + + if (res == -1 && errno != EINTR) + break; + } + /* Something broke with the main thread pipe, so we ignore it for now. + Most probably erts has closed this pipe and is about to exit. */ +#endif /* #ifdef __DARWIN__ */ + + while (1) { #ifdef DEBUG int res = #else @@ -3321,7 +3335,6 @@ erts_sys_main_thread(void) select(0, NULL, NULL, NULL, NULL); ASSERT(res < 0); ASSERT(errno == EINTR); -#endif } } -- cgit v1.2.3