aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/unix
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2016-12-15 15:40:19 +0100
committerBjörn-Egil Dahlberg <[email protected]>2016-12-15 15:40:19 +0100
commit93468dcbce14d002ec7e3525c813b83d33616d3d (patch)
tree13f588eb33d8a5ffa2f0a949b346282e78601472 /erts/emulator/sys/unix
parent37933d48e1569bdf538686d8a1f82e7be4125ed5 (diff)
parentc643ad3897587660ebd06afcef5e3dfc7f6c1180 (diff)
downloadotp-93468dcbce14d002ec7e3525c813b83d33616d3d.tar.gz
otp-93468dcbce14d002ec7e3525c813b83d33616d3d.tar.bz2
otp-93468dcbce14d002ec7e3525c813b83d33616d3d.zip
Merge branch 'egil/erts/handle-sigterm-nicely/OTP-14085' into maint
* egil/erts/handle-sigterm-nicely/OTP-14085: erts: Document SIGTERM handler erts: Add SIGTERM signal handler
Diffstat (limited to 'erts/emulator/sys/unix')
-rw-r--r--erts/emulator/sys/unix/sys.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 4b2edace0a..2fc802a2c6 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -407,6 +407,7 @@ erts_sys_pre_init(void)
#ifdef ERTS_THR_HAVE_SIG_FUNCS
sigemptyset(&thr_create_sigmask);
sigaddset(&thr_create_sigmask, SIGINT); /* block interrupt */
+ sigaddset(&thr_create_sigmask, SIGTERM); /* block terminate signal */
sigaddset(&thr_create_sigmask, SIGUSR1); /* block user defined signal */
#endif
@@ -655,6 +656,40 @@ static RETSIGTYPE request_break(int signum)
#endif
}
+static void stop_requested(void) {
+ Process* p = NULL;
+ Eterm msg, *hp;
+ ErtsProcLocks locks = 0;
+ ErlOffHeap *ohp;
+ Eterm id = erts_whereis_name_to_id(NULL, am_init);
+
+ if ((p = (erts_pid2proc_opt(NULL, 0, id, 0, ERTS_P2P_FLG_INC_REFC))) != NULL) {
+ ErtsMessage *msgp = erts_alloc_message_heap(p, &locks, 3, &hp, &ohp);
+
+ /* init ! {stop,stop} */
+ msg = TUPLE2(hp, am_stop, am_stop);
+ erts_queue_message(p, locks, msgp, msg, am_system);
+
+ if (locks)
+ erts_smp_proc_unlock(p, locks);
+ erts_proc_dec_refc(p);
+ }
+}
+
+#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
+static RETSIGTYPE request_stop(void)
+#else
+static RETSIGTYPE request_stop(int signum)
+#endif
+{
+#ifdef ERTS_SMP
+ smp_sig_notify('S');
+#else
+ stop_requested();
+#endif
+}
+
+
static ERTS_INLINE void
sigusr1_exit(void)
{
@@ -751,6 +786,7 @@ static RETSIGTYPE do_quit(int signum)
/* Disable break */
void erts_set_ignore_break(void) {
sys_signal(SIGINT, SIG_IGN);
+ sys_signal(SIGTERM, SIG_IGN);
sys_signal(SIGQUIT, SIG_IGN);
sys_signal(SIGTSTP, SIG_IGN);
}
@@ -776,6 +812,7 @@ void erts_replace_intr(void) {
void init_break_handler(void)
{
sys_signal(SIGINT, request_break);
+ sys_signal(SIGTERM, request_stop);
#ifndef ETHR_UNUSABLE_SIGUSRX
sys_signal(SIGUSR1, user_signal1);
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
@@ -1289,6 +1326,9 @@ signal_dispatcher_thread_func(void *unused)
switch (buf[i]) {
case 0: /* Emulator initialized */
break;
+ case 'S': /* SIGTERM */
+ stop_requested();
+ break;
case 'I': /* SIGINT */
break_requested();
break;