From 0dec7ddb341b2b7d2643f86dd9e9497b3f5268a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 21 Mar 2017 10:48:15 +0100 Subject: erts: Don't allocate memory during signal handling Allocations and message sending are now scheduled by a signal, via a signal state bitmap, instead of doing it directly in the signal handler. --- erts/emulator/sys/common/erl_check_io.c | 14 ++++++++ erts/emulator/sys/unix/sys.c | 64 +++++++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 2 deletions(-) (limited to 'erts/emulator/sys') diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c index 1ef9fa2a05..00c70268df 100644 --- a/erts/emulator/sys/common/erl_check_io.c +++ b/erts/emulator/sys/common/erl_check_io.c @@ -2169,6 +2169,12 @@ ERTS_CIO_EXPORT(erts_check_io)(int do_wait) erts_do_break_handling(); #endif +#ifdef ERTS_SIGNAL_STATE /* ifndef ERTS_SMP */ + if (ERTS_SIGNAL_STATE) { + erts_handle_signal_state(); + } +#endif + /* Figure out timeout value */ timeout_time = (do_wait ? erts_check_next_timeout_time(esdp) @@ -2207,6 +2213,14 @@ ERTS_CIO_EXPORT(erts_check_io)(int do_wait) erts_do_break_handling(); #endif + +#ifdef ERTS_SIGNAL_STATE /* ifndef ERTS_SMP */ + if (ERTS_SIGNAL_STATE) { + erts_handle_signal_state(); + } +#endif + + if (poll_ret != 0) { erts_smp_atomic_set_nob(&pollset.in_poll_wait, 0); forget_removed(&pollset); diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index e836f9bcc8..b48b3f8804 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -139,6 +139,28 @@ volatile int erts_break_requested = 0; #define ERTS_SET_BREAK_REQUESTED (erts_break_requested = 1) #define ERTS_UNSET_BREAK_REQUESTED (erts_break_requested = 0) #endif + +#ifndef ERTS_SMP +static Eterm signalstate_sigterm[] = { + am_sigint, /* 0 */ + am_sighup, /* 1 */ + am_sigquit, /* 2 */ + am_sigabrt, /* 3 */ + am_sigalrm, /* 4 */ + am_sigterm, /* 5 */ + am_sigusr1, /* 6 */ + am_sigusr2, /* 7 */ + am_sigchld, /* 8 */ + am_sigstop, /* 9 */ + am_sigtstp /* 10 */ +}; + +volatile Uint erts_signal_state = 0; +#define ERTS_SET_SIGNAL_STATE(S) (erts_signal_state |= signum_to_signalstate(S)) +#define ERTS_CLEAR_SIGNAL_STATE (erts_signal_state = 0) +static ERTS_INLINE Uint signum_to_signalstate(int signum); +#endif + /* set early so the break handler has access to initial mode */ static struct termios initial_tty_mode; static int replace_intr = 0; @@ -770,13 +792,34 @@ signum_to_signalterm(int signum) } } +#ifndef ERTS_SMP +static ERTS_INLINE Uint +signum_to_signalstate(int signum) +{ + switch (signum) { + case SIGINT: return (1 << 0); + case SIGHUP: return (1 << 1); + case SIGQUIT: return (1 << 2); + case SIGABRT: return (1 << 3); + case SIGALRM: return (1 << 4); + case SIGTERM: return (1 << 5); + case SIGUSR1: return (1 << 6); + case SIGUSR2: return (1 << 7); + case SIGCHLD: return (1 << 8); + case SIGSTOP: return (1 << 9); + case SIGTSTP: return (1 << 10); + default: return 0; + } +} +#endif + static RETSIGTYPE generic_signal_handler(int signum) { #ifdef ERTS_SMP smp_sig_notify(signum); #else - Eterm signal = signum_to_signalterm(signum); - signal_notify_requested(signal); + ERTS_SET_SIGNAL_STATE(signum); + ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */ #endif } @@ -962,6 +1005,23 @@ void erts_do_break_handling(void) erts_smp_thr_progress_unblock(); } +#ifdef ERTS_SIGNAL_STATE +void erts_handle_signal_state(void) { + Uint signal_state = ERTS_SIGNAL_STATE; + Uint i = 0; + + ERTS_CLEAR_SIGNAL_STATE; + + while (signal_state) { + if (signal_state & 0x1) { + signal_notify_requested(signalstate_sigterm[i]); + } + i++; + signal_state = signal_state >> 1; + } +} +#endif + /* Fills in the systems representation of the jam/beam process identifier. ** The Pid is put in STRING representation in the supplied buffer, ** no interpretatione of this should be done by the rest of the -- cgit v1.2.3