aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2017-03-21 10:48:15 +0100
committerBjörn-Egil Dahlberg <[email protected]>2017-03-22 10:59:06 +0100
commit0dec7ddb341b2b7d2643f86dd9e9497b3f5268a7 (patch)
treeddd716eb7fa7a1b9bb7a66b9c014990f69077777
parent303f4781e485f66e1eb6c5db77ff9523e5f69b7e (diff)
downloadotp-0dec7ddb341b2b7d2643f86dd9e9497b3f5268a7.tar.gz
otp-0dec7ddb341b2b7d2643f86dd9e9497b3f5268a7.tar.bz2
otp-0dec7ddb341b2b7d2643f86dd9e9497b3f5268a7.zip
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.
-rw-r--r--erts/emulator/beam/sys.h6
-rw-r--r--erts/emulator/sys/common/erl_check_io.c14
-rw-r--r--erts/emulator/sys/unix/sys.c64
3 files changed, 82 insertions, 2 deletions
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index c6ea8049c3..144dd60d21 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -487,6 +487,12 @@ extern volatile int erts_break_requested;
void erts_do_break_handling(void);
#endif
+#if !defined(ERTS_SMP) && !defined(__WIN32__)
+extern volatile Uint erts_signal_state;
+#define ERTS_SIGNAL_STATE erts_signal_state
+void erts_handle_signal_state(void);
+#endif
+
#ifdef ERTS_SMP
extern erts_smp_atomic32_t erts_writing_erl_crash_dump;
extern erts_tsd_key_t erts_is_crash_dumping_key;
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