From dc72c879b68fdf96edfec360e8c311ff7389ecc6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Fri, 16 Dec 2016 10:08:16 +0100
Subject: erts: Remove whitespace errors
* and some minor refactoring
---
erts/emulator/sys/unix/sys.c | 78 ++++++++++++--------------------------------
1 file changed, 20 insertions(+), 58 deletions(-)
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 2fc802a2c6..2ce0d56dde 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -153,7 +153,7 @@ volatile int erts_break_requested = 0;
static struct termios initial_tty_mode;
static int replace_intr = 0;
/* assume yes initially, ttsl_init will clear it */
-int using_oldshell = 1;
+int using_oldshell = 1;
#ifdef ERTS_ENABLE_KERNEL_POLL
@@ -798,11 +798,11 @@ void erts_replace_intr(void) {
if (isatty(0)) {
tcgetattr(0, &mode);
-
+
/* here's an example of how to replace ctrl-c with ctrl-u */
/* mode.c_cc[VKILL] = 0;
mode.c_cc[VINTR] = CKILL; */
-
+
mode.c_cc[VINTR] = 0; /* disable ctrl-c */
tcsetattr(0, TCSANOW, &mode);
replace_intr = 1;
@@ -856,10 +856,7 @@ get_number(char **str_ptr)
}
}
-void
-os_flavor(char* namebuf, /* Where to return the name. */
- unsigned size) /* Size of name buffer. */
-{
+void os_flavor(char* namebuf, unsigned size) {
struct utsname uts; /* Information about the system. */
char* s;
@@ -872,22 +869,16 @@ os_flavor(char* namebuf, /* Where to return the name. */
strcpy(namebuf, uts.sysname);
}
-void
-os_version(pMajor, pMinor, pBuild)
-int* pMajor; /* Pointer to major version. */
-int* pMinor; /* Pointer to minor version. */
-int* pBuild; /* Pointer to build number. */
-{
+void os_version(int *pMajor, int *pMinor, int *pBuild) {
struct utsname uts; /* Information about the system. */
char* release; /* Pointer to the release string:
- * X.Y or X.Y.Z.
- */
+ * X.Y or X.Y.Z. */
(void) uname(&uts);
release = uts.release;
- *pMajor = get_number(&release);
- *pMinor = get_number(&release);
- *pBuild = get_number(&release);
+ *pMajor = get_number(&release); /* Pointer to major version. */
+ *pMinor = get_number(&release); /* Pointer to minor version. */
+ *pBuild = get_number(&release); /* Pointer to build number. */
}
void init_getenv_state(GETENV_STATE *state)
@@ -922,7 +913,7 @@ void erts_do_break_handling(void)
{
struct termios temp_mode;
int saved = 0;
-
+
/*
* Most functions that do_break() calls are intentionally not thread safe;
* therefore, make sure that all threads but this one are blocked before
@@ -940,14 +931,14 @@ void erts_do_break_handling(void)
tcsetattr(0,TCSANOW,&initial_tty_mode);
saved = 1;
}
-
+
/* call the break handling function, reset the flag */
do_break();
ERTS_UNSET_BREAK_REQUESTED;
fflush(stdout);
-
+
/* after break we go back to saved settings */
if (using_oldshell && !replace_intr) {
SET_NONBLOCKING(1);
@@ -1055,37 +1046,12 @@ erts_sys_unsetenv(char *key)
return res;
}
-void
-sys_init_io(void)
-{
-}
-
-#if (0) /* unused? */
-static int write_fill(fd, buf, len)
-int fd, len;
-char *buf;
-{
- int i, done = 0;
-
- do {
- if ((i = write(fd, buf+done, len-done)) < 0) {
- if (errno != EINTR)
- return (i);
- i = 0;
- }
- done += i;
- } while (done < len);
- return (len);
-}
-#endif
+void sys_init_io(void) { }
+void erts_sys_alloc_init(void) { }
extern const char pre_loaded_code[];
extern Preload pre_loaded[];
-void erts_sys_alloc_init(void)
-{
-}
-
#if ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
void *erts_sys_aligned_alloc(UWord alignment, UWord size)
{
@@ -1186,9 +1152,7 @@ void sys_preload_end(Preload* p)
Here we assume that all schedulers are stopped so that erl_poll
does not interfere with the select below.
*/
-int sys_get_key(fd)
-int fd;
-{
+int sys_get_key(int fd) {
int c, ret;
unsigned char rbuf[64];
fd_set fds;
@@ -1207,15 +1171,14 @@ int fd;
if (c <= 0)
return c;
}
-
- return rbuf[0];
+ return rbuf[0];
}
extern int erts_initialized;
void
erl_assert_error(const char* expr, const char* func, const char* file, int line)
-{
+{
fflush(stdout);
fprintf(stderr, "%s:%d:%s() Assertion failed: %s\n",
file, line, func, expr);
@@ -1240,7 +1203,7 @@ erl_debug(char* fmt, ...)
{
char sbuf[1024]; /* Temporary buffer. */
va_list va;
-
+
if (debug_log) {
va_start(va, fmt);
vsprintf(sbuf, fmt, va);
@@ -1388,9 +1351,9 @@ init_smp_sig_suspend(void) {
int erts_darwin_main_thread_pipe[2];
int erts_darwin_main_thread_result_pipe[2];
-static void initialize_darwin_main_thread_pipes(void)
+static void initialize_darwin_main_thread_pipes(void)
{
- if (pipe(erts_darwin_main_thread_pipe) < 0 ||
+ if (pipe(erts_darwin_main_thread_pipe) < 0 ||
pipe(erts_darwin_main_thread_result_pipe) < 0) {
erts_exit(ERTS_ERROR_EXIT,"Fatal error initializing Darwin main thread stealing");
}
@@ -1556,5 +1519,4 @@ erl_sys_args(int* argc, char** argv)
argv[j++] = argv[i];
}
*argc = j;
-
}
--
cgit v1.2.3
From c9060f9b4289bf9a669ac651a1a7aeb97a28652c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Mon, 13 Apr 2015 18:03:33 +0200
Subject: erts: Add SIGHUP signal handler
A received SIGHUP signal to beam will generate a '{notify, sighup}' message
to the registered process 'erl_signal_server'. 'erl_signal_server' is a
gen_event process.
---
erts/emulator/beam/atom.names | 2 ++
erts/emulator/beam/register.c | 12 ++++++------
erts/emulator/sys/unix/sys.c | 41 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index b1aeed7889..363b17e27c 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -239,6 +239,7 @@ atom Eq='=:='
atom Eqeq='=='
atom erl_tracer
atom erlang
+atom erl_signal_server
atom ERROR='ERROR'
atom error_handler
atom error_logger
@@ -590,6 +591,7 @@ atom set_tcw
atom set_tcw_fake
atom separate
atom shared
+atom sighup
atom silent
atom size
atom sl_alloc
diff --git a/erts/emulator/beam/register.c b/erts/emulator/beam/register.c
index acda51c9fc..7f60710124 100644
--- a/erts/emulator/beam/register.c
+++ b/erts/emulator/beam/register.c
@@ -272,13 +272,13 @@ erts_whereis_name_to_id(Process *c_p, Eterm name)
int ix;
HashBucket* b;
#ifdef ERTS_SMP
- ErtsProcLocks c_p_locks = c_p ? ERTS_PROC_LOCK_MAIN : 0;
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
- if (c_p) ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(c_p);
-#endif
-
+ ErtsProcLocks c_p_locks = 0;
+ if (c_p) {
+ c_p_locks = ERTS_PROC_LOCK_MAIN;
+ ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(c_p);
+ }
reg_safe_read_lock(c_p, &c_p_locks);
+
if (c_p && !c_p_locks)
erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
#endif
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 2ce0d56dde..a099662b16 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -408,6 +408,7 @@ erts_sys_pre_init(void)
sigemptyset(&thr_create_sigmask);
sigaddset(&thr_create_sigmask, SIGINT); /* block interrupt */
sigaddset(&thr_create_sigmask, SIGTERM); /* block terminate signal */
+ sigaddset(&thr_create_sigmask, SIGHUP); /* block sighups */
sigaddset(&thr_create_sigmask, SIGUSR1); /* block user defined signal */
#endif
@@ -625,6 +626,28 @@ int erts_sys_prepare_crash_dump(int secs)
return prepare_crash_dump(secs);
}
+static void signal_notify_requested(Eterm type) {
+ Process* p = NULL;
+ Eterm msg, *hp;
+ ErtsProcLocks locks = 0;
+ ErlOffHeap *ohp;
+
+ Eterm id = erts_whereis_name_to_id(NULL, am_erl_signal_server);
+
+ 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);
+
+ /* erl_signal_server ! {notify, sighup} */
+ msg = TUPLE2(hp, am_notify, type);
+ erts_queue_message(p, locks, msgp, msg, am_system);
+
+ if (locks)
+ erts_smp_proc_unlock(p, locks);
+ erts_proc_dec_refc(p);
+ }
+}
+
+
static ERTS_INLINE void
break_requested(void)
{
@@ -783,10 +806,24 @@ static RETSIGTYPE do_quit(int signum)
#endif
}
+#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
+static RETSIGTYPE request_sighup(void)
+#else
+static RETSIGTYPE request_sighup(int signum)
+#endif
+{
+#ifdef ERTS_SMP
+ smp_sig_notify('H');
+#else
+ signal_notify_requested(am_sighup);
+#endif
+}
+
/* Disable break */
void erts_set_ignore_break(void) {
sys_signal(SIGINT, SIG_IGN);
sys_signal(SIGTERM, SIG_IGN);
+ sys_signal(SIGHUP, SIG_IGN);
sys_signal(SIGQUIT, SIG_IGN);
sys_signal(SIGTSTP, SIG_IGN);
}
@@ -813,6 +850,7 @@ void init_break_handler(void)
{
sys_signal(SIGINT, request_break);
sys_signal(SIGTERM, request_stop);
+ sys_signal(SIGHUP, request_sighup);
#ifndef ETHR_UNUSABLE_SIGUSRX
sys_signal(SIGUSR1, user_signal1);
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
@@ -1289,6 +1327,9 @@ signal_dispatcher_thread_func(void *unused)
switch (buf[i]) {
case 0: /* Emulator initialized */
break;
+ case 'H': /* SIGHUP */
+ signal_notify_requested(am_sighup);
+ break;
case 'S': /* SIGTERM */
stop_requested();
break;
--
cgit v1.2.3
From a7b52ad679e6a58a9351a26e198eee70067b000f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Mon, 13 Apr 2015 18:47:06 +0200
Subject: kernel: Add gen_event signal server and default handler
---
lib/kernel/src/Makefile | 1 +
lib/kernel/src/erl_signal_handler.erl | 47 +++++++++++++++++++++++++++++++++++
lib/kernel/src/kernel.app.src | 1 +
lib/kernel/src/kernel.erl | 13 +++++++++-
4 files changed, 61 insertions(+), 1 deletion(-)
create mode 100644 lib/kernel/src/erl_signal_handler.erl
diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile
index 2b72f78dcf..2a89faaf13 100644
--- a/lib/kernel/src/Makefile
+++ b/lib/kernel/src/Makefile
@@ -71,6 +71,7 @@ MODULES = \
erl_distribution \
erl_epmd \
erl_reply \
+ erl_signal_handler \
erts_debug \
error_handler \
error_logger \
diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl
new file mode 100644
index 0000000000..6bd8f992a7
--- /dev/null
+++ b/lib/kernel/src/erl_signal_handler.erl
@@ -0,0 +1,47 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2013. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(erl_signal_handler).
+-behaviour(gen_event).
+-export([init/1, format_status/2,
+ handle_event/2, handle_call/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-record(state,{}).
+
+init(_Args) ->
+ {ok, #state{}}.
+
+handle_event(_SignalMsg, S) ->
+ {ok, S}.
+
+handle_info(_Info, S) ->
+ {ok, S}.
+
+handle_call(_Request, S) ->
+ {ok, ok, S}.
+
+format_status(_Opt, [_Pdict,_S]) ->
+ ok.
+
+code_change(_OldVsn, S, _Extra) ->
+ {ok, S}.
+
+terminate(_Args, _S) ->
+ ok.
diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src
index 4d08a55c7c..25e4ddd95c 100644
--- a/lib/kernel/src/kernel.app.src
+++ b/lib/kernel/src/kernel.app.src
@@ -34,6 +34,7 @@
erl_boot_server,
erl_distribution,
erl_reply,
+ erl_signal_handler,
error_handler,
error_logger,
file,
diff --git a/lib/kernel/src/kernel.erl b/lib/kernel/src/kernel.erl
index 3d0ef81318..59eca242b1 100644
--- a/lib/kernel/src/kernel.erl
+++ b/lib/kernel/src/kernel.erl
@@ -32,6 +32,14 @@
start(_, []) ->
case supervisor:start_link({local, kernel_sup}, kernel, []) of
{ok, Pid} ->
+ %% add signal handler
+ case whereis(erl_signal_server) of
+ %% in case of minimal mode
+ undefined -> ok;
+ _ ->
+ ok = gen_event:add_handler(erl_signal_server, erl_signal_handler, [])
+ end,
+ %% add error handler
Type = get_error_logger_type(),
case error_logger:swap_handler(Type) of
ok -> {ok, Pid, []};
@@ -131,6 +139,9 @@ init([]) ->
permanent, 2000, worker, [inet_db]},
NetSup = {net_sup, {erl_distribution, start_link, []},
permanent, infinity, supervisor,[erl_distribution]},
+ SigSrv = #{id => erl_signal_server,
+ start => {gen_event, start_link, [{local, erl_signal_server}]},
+ type => worker, restart => permanent, shutdown => 2000, modules => dynamic},
DistAC = start_dist_ac(),
Timer = start_timer(),
@@ -141,7 +152,7 @@ init([]) ->
permanent, infinity, supervisor, [?MODULE]},
{ok, {SupFlags,
[Code, Rpc, Global, InetDb | DistAC] ++
- [NetSup, Glo_grp, File,
+ [NetSup, Glo_grp, File, SigSrv,
StdError, User, Config, SafeSupervisor] ++ Timer}}
end;
init(safe) ->
--
cgit v1.2.3
From 40c82769def0cfa59e75669ff1c6fc4abcecd764 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Thu, 15 Dec 2016 18:07:13 +0100
Subject: erts: Handle SIGTERM via signal service instead
---
erts/emulator/beam/atom.names | 1 +
erts/emulator/sys/unix/sys.c | 28 ++++------------------------
lib/kernel/src/erl_signal_handler.erl | 4 ++++
3 files changed, 9 insertions(+), 24 deletions(-)
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 363b17e27c..52a3413796 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -592,6 +592,7 @@ atom set_tcw_fake
atom separate
atom shared
atom sighup
+atom sigterm
atom silent
atom size
atom sl_alloc
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index a099662b16..cb9ed2de76 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -679,26 +679,6 @@ 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
@@ -706,9 +686,9 @@ static RETSIGTYPE request_stop(int signum)
#endif
{
#ifdef ERTS_SMP
- smp_sig_notify('S');
+ smp_sig_notify('T');
#else
- stop_requested();
+ signal_notify_requested(am_sigterm);
#endif
}
@@ -1330,8 +1310,8 @@ signal_dispatcher_thread_func(void *unused)
case 'H': /* SIGHUP */
signal_notify_requested(am_sighup);
break;
- case 'S': /* SIGTERM */
- stop_requested();
+ case 'T': /* SIGTERM */
+ signal_notify_requested(am_sigterm);
break;
case 'I': /* SIGINT */
break_requested();
diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl
index 6bd8f992a7..04130eac66 100644
--- a/lib/kernel/src/erl_signal_handler.erl
+++ b/lib/kernel/src/erl_signal_handler.erl
@@ -28,6 +28,10 @@
init(_Args) ->
{ok, #state{}}.
+handle_event(sigterm, S) ->
+ error_logger:info_msg("SIGTERM received - shutting down~n"),
+ ok = init:stop(),
+ {ok, S};
handle_event(_SignalMsg, S) ->
{ok, S}.
--
cgit v1.2.3
From 2d3bf84d8167b50728b0a5411a4e2dfa71d52c10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Fri, 16 Dec 2016 12:24:13 +0100
Subject: erts: Handle SIGUSR1 via signal service instead
---
erts/emulator/beam/atom.names | 1 +
erts/emulator/beam/sys.h | 14 ------------
erts/emulator/sys/common/erl_poll.c | 1 -
erts/emulator/sys/unix/sys.c | 42 ++++-------------------------------
lib/kernel/src/erl_signal_handler.erl | 3 +++
5 files changed, 8 insertions(+), 53 deletions(-)
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 52a3413796..668abfaaee 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -593,6 +593,7 @@ atom separate
atom shared
atom sighup
atom sigterm
+atom sigusr1
atom silent
atom size
atom sl_alloc
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 4b3ac594a0..ceea794cc4 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -487,20 +487,6 @@ extern volatile int erts_break_requested;
void erts_do_break_handling(void);
#endif
-#ifdef ERTS_WANT_GOT_SIGUSR1
-# ifndef UNIX
-# define ERTS_GOT_SIGUSR1 0
-# else
-# ifdef ERTS_SMP
-extern erts_smp_atomic32_t erts_got_sigusr1;
-# define ERTS_GOT_SIGUSR1 ((int) erts_smp_atomic32_read_mb(&erts_got_sigusr1))
-# else
-extern volatile int erts_got_sigusr1;
-# define ERTS_GOT_SIGUSR1 erts_got_sigusr1
-# endif
-# endif
-#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_poll.c b/erts/emulator/sys/common/erl_poll.c
index b8a28bcc18..5e7ae8953a 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -51,7 +51,6 @@
#ifndef WANT_NONBLOCKING
# define WANT_NONBLOCKING
#endif
-#define ERTS_WANT_GOT_SIGUSR1
#include "erl_poll.h"
#if ERTS_POLL_USE_KQUEUE
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index cb9ed2de76..de9c1b2ca0 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -50,7 +50,6 @@
#endif
#define ERTS_WANT_BREAK_HANDLING
-#define ERTS_WANT_GOT_SIGUSR1
#define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */
#include "sys.h"
#include "erl_thr_progress.h"
@@ -96,18 +95,10 @@ static int debug_log = 0;
#endif
#ifdef ERTS_SMP
-erts_smp_atomic32_t erts_got_sigusr1;
-#define ERTS_SET_GOT_SIGUSR1 \
- erts_smp_atomic32_set_mb(&erts_got_sigusr1, 1)
-#define ERTS_UNSET_GOT_SIGUSR1 \
- erts_smp_atomic32_set_mb(&erts_got_sigusr1, 0)
static erts_smp_atomic32_t have_prepared_crash_dump;
#define ERTS_PREPARED_CRASH_DUMP \
((int) erts_smp_atomic32_xchg_nob(&have_prepared_crash_dump, 1))
#else
-volatile int erts_got_sigusr1;
-#define ERTS_SET_GOT_SIGUSR1 (erts_got_sigusr1 = 1)
-#define ERTS_UNSET_GOT_SIGUSR1 (erts_got_sigusr1 = 0)
static volatile int have_prepared_crash_dump;
#define ERTS_PREPARED_CRASH_DUMP \
(have_prepared_crash_dump++)
@@ -430,11 +421,9 @@ erts_sys_pre_init(void)
#ifdef ERTS_SMP
erts_smp_atomic32_init_nob(&erts_break_requested, 0);
- erts_smp_atomic32_init_nob(&erts_got_sigusr1, 0);
erts_smp_atomic32_init_nob(&have_prepared_crash_dump, 0);
#else
erts_break_requested = 0;
- erts_got_sigusr1 = 0;
have_prepared_crash_dump = 0;
#endif
@@ -692,29 +681,6 @@ static RETSIGTYPE request_stop(int signum)
#endif
}
-
-static ERTS_INLINE void
-sigusr1_exit(void)
-{
- char env[21]; /* enough to hold any 64-bit integer */
- size_t envsz;
- int i, secs = -1;
-
- /* We do this at interrupt level, since the main reason for
- * wanting to generate a crash dump in this way is that the emulator
- * is hung somewhere, so it won't be able to poll any flag we set here.
- */
- ERTS_SET_GOT_SIGUSR1;
-
- envsz = sizeof(env);
- if ((i = erts_sys_getenv_raw("ERL_CRASH_DUMP_SECONDS", env, &envsz)) >= 0) {
- secs = i != 0 ? 0 : atoi(env);
- }
-
- prepare_crash_dump(secs);
- erts_exit(ERTS_DUMP_EXIT, "Received SIGUSR1\n");
-}
-
#ifdef ETHR_UNUSABLE_SIGUSRX
#warning "Unusable SIGUSR1 & SIGUSR2. Disabling use of these signals"
@@ -744,7 +710,7 @@ static RETSIGTYPE user_signal1(int signum)
#ifdef ERTS_SMP
smp_sig_notify('1');
#else
- sigusr1_exit();
+ signal_notify_requested(am_sigusr1);
#endif
}
@@ -1313,15 +1279,15 @@ signal_dispatcher_thread_func(void *unused)
case 'T': /* SIGTERM */
signal_notify_requested(am_sigterm);
break;
+ case '1': /* SIGUSR1 */
+ signal_notify_requested(am_sigusr1);
+ break;
case 'I': /* SIGINT */
break_requested();
break;
case 'Q': /* SIGQUIT */
quit_requested();
break;
- case '1': /* SIGUSR1 */
- sigusr1_exit();
- break;
default:
erts_exit(ERTS_ABORT_EXIT,
"signal-dispatcher thread received unknown "
diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl
index 04130eac66..43cc307ffd 100644
--- a/lib/kernel/src/erl_signal_handler.erl
+++ b/lib/kernel/src/erl_signal_handler.erl
@@ -28,6 +28,9 @@
init(_Args) ->
{ok, #state{}}.
+handle_event(sigusr1, S) ->
+ erlang:halt("Received SIGUSR1"),
+ {ok, S};
handle_event(sigterm, S) ->
error_logger:info_msg("SIGTERM received - shutting down~n"),
ok = init:stop(),
--
cgit v1.2.3
From afbec46949f0d31448386234efa89cec78b905e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Mon, 16 Jan 2017 11:52:39 +0100
Subject: erts: Add OS signal tests
---
erts/emulator/test/Makefile | 1 +
erts/emulator/test/os_signal_SUITE.erl | 354 +++++++++++++++++++++
.../test/os_signal_SUITE_data/Makefile.src | 6 +
.../test/os_signal_SUITE_data/os_signal_nif.c | 66 ++++
4 files changed, 427 insertions(+)
create mode 100644 erts/emulator/test/os_signal_SUITE.erl
create mode 100644 erts/emulator/test/os_signal_SUITE_data/Makefile.src
create mode 100644 erts/emulator/test/os_signal_SUITE_data/os_signal_nif.c
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile
index 2e48c475d5..5ec6ff1901 100644
--- a/erts/emulator/test/Makefile
+++ b/erts/emulator/test/Makefile
@@ -85,6 +85,7 @@ MODULES= \
num_bif_SUITE \
message_queue_data_SUITE \
op_SUITE \
+ os_signal_SUITE \
port_SUITE \
port_bif_SUITE \
process_SUITE \
diff --git a/erts/emulator/test/os_signal_SUITE.erl b/erts/emulator/test/os_signal_SUITE.erl
new file mode 100644
index 0000000000..2b9343663d
--- /dev/null
+++ b/erts/emulator/test/os_signal_SUITE.erl
@@ -0,0 +1,354 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% File: os_signal_SUITE.erl
+%% Author: Björn-Egil Dahlberg
+%% Created: 2017-01-13
+%%
+
+-module(os_signal_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-export([all/0, suite/0]).
+-export([init_per_testcase/2, end_per_testcase/2]).
+-export([init_per_suite/1, end_per_suite/1]).
+
+-export([set_alarm/1, fork/0, get_exit_code/1]).
+
+% Test cases
+-export([set_unset/1,
+ t_sighup/1,
+ t_sigusr1/1,
+ t_sigusr2/1,
+ t_sigterm/1,
+ t_sigalrm/1,
+ t_sigchld/1,
+ t_sigchld_fork/1]).
+
+-define(signal_server, erl_signal_server).
+
+suite() ->
+ [{ct_hooks,[ts_install_cth]},
+ {timetrap, {minutes, 2}}].
+
+all() ->
+ case os:type() of
+ {win32, _} -> [];
+ _ -> [set_unset,
+ t_sighup,
+ t_sigusr1,
+ t_sigusr2,
+ t_sigterm,
+ t_sigalrm,
+ t_sigchld,
+ t_sigchld_fork]
+ end.
+
+init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
+ Pid = erlang:whereis(?signal_server),
+ true = erlang:unregister(?signal_server),
+ [{signal_server, Pid}|Config].
+
+end_per_testcase(_Func, Config) ->
+ case proplists:get_value(signal_server, Config) of
+ undefined -> ok;
+ Pid ->
+ true = erlang:register(?signal_server, Pid),
+ ok
+ end.
+
+init_per_suite(Config) ->
+ load_nif(Config),
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+%% tests
+
+set_unset(_Config) ->
+ Signals = [sighup, %sigint,
+ sigquit, sigill,
+ sigabrt,
+ sigalrm, sigterm,
+ sigusr1, sigusr2,
+ sigchld,
+ sigstop, sigtstp],
+ F1 = fun(Sig) -> true = erts_internal:set_signal(Sig,handle) end,
+ F2 = fun(Sig) -> true = erts_internal:set_signal(Sig,default) end,
+ F3 = fun(Sig) -> true = erts_internal:set_signal(Sig,ignore) end,
+ %% set handle
+ ok = lists:foreach(F1, Signals),
+ %% set ignore
+ ok = lists:foreach(F2, Signals),
+ %% set default
+ ok = lists:foreach(F3, Signals),
+ ok.
+
+t_sighup(_Config) ->
+ Pid1 = setup_service(),
+ OsPid = os:getpid(),
+ erts_internal:set_signal(sighup, handle),
+ ok = kill("HUP", OsPid),
+ ok = kill("HUP", OsPid),
+ ok = kill("HUP", OsPid),
+ Msgs1 = fetch_msgs(Pid1),
+ io:format("Msgs1: ~p~n", [Msgs1]),
+ [{notify,sighup},
+ {notify,sighup},
+ {notify,sighup}] = Msgs1,
+ %% no proc
+ ok = kill("HUP", OsPid),
+ ok = kill("HUP", OsPid),
+ ok = kill("HUP", OsPid),
+ %% ignore
+ Pid2 = setup_service(),
+ erts_internal:set_signal(sighup, ignore),
+ ok = kill("HUP", OsPid),
+ ok = kill("HUP", OsPid),
+ ok = kill("HUP", OsPid),
+ Msgs2 = fetch_msgs(Pid2),
+ io:format("Msgs2: ~p~n", [Msgs2]),
+ [] = Msgs2,
+ %% reset to handle (it's the default)
+ erts_internal:set_signal(sighup, handle),
+ ok.
+
+t_sigusr1(_Config) ->
+ Pid1 = setup_service(),
+ OsPid = os:getpid(),
+ erts_internal:set_signal(sigusr1, handle),
+ ok = kill("USR1", OsPid),
+ ok = kill("USR1", OsPid),
+ ok = kill("USR1", OsPid),
+ Msgs1 = fetch_msgs(Pid1),
+ io:format("Msgs1: ~p~n", [Msgs1]),
+ [{notify,sigusr1},
+ {notify,sigusr1},
+ {notify,sigusr1}] = Msgs1,
+ %% no proc
+ ok = kill("USR1", OsPid),
+ ok = kill("USR1", OsPid),
+ ok = kill("USR1", OsPid),
+ %% ignore
+ Pid2 = setup_service(),
+ erts_internal:set_signal(sigusr1, ignore),
+ ok = kill("USR1", OsPid),
+ ok = kill("USR1", OsPid),
+ ok = kill("USR1", OsPid),
+ Msgs2 = fetch_msgs(Pid2),
+ io:format("Msgs2: ~p~n", [Msgs2]),
+ [] = Msgs2,
+ %% reset to ignore (it's the default)
+ erts_internal:set_signal(sigusr1, handle),
+ ok.
+
+t_sigusr2(_Config) ->
+ Pid1 = setup_service(),
+ OsPid = os:getpid(),
+ erts_internal:set_signal(sigusr2, handle),
+ ok = kill("USR2", OsPid),
+ ok = kill("USR2", OsPid),
+ ok = kill("USR2", OsPid),
+ Msgs1 = fetch_msgs(Pid1),
+ io:format("Msgs1: ~p~n", [Msgs1]),
+ [{notify,sigusr2},
+ {notify,sigusr2},
+ {notify,sigusr2}] = Msgs1,
+ %% no proc
+ ok = kill("USR2", OsPid),
+ ok = kill("USR2", OsPid),
+ ok = kill("USR2", OsPid),
+ %% ignore
+ Pid2 = setup_service(),
+ erts_internal:set_signal(sigusr2, ignore),
+ ok = kill("USR2", OsPid),
+ ok = kill("USR2", OsPid),
+ ok = kill("USR2", OsPid),
+ Msgs2 = fetch_msgs(Pid2),
+ io:format("Msgs2: ~p~n", [Msgs2]),
+ [] = Msgs2,
+ %% reset to ignore (it's the default)
+ erts_internal:set_signal(sigusr2, ignore),
+ ok.
+
+t_sigterm(_Config) ->
+ Pid1 = setup_service(),
+ OsPid = os:getpid(),
+ erts_internal:set_signal(sigterm, handle),
+ ok = kill("TERM", OsPid),
+ ok = kill("TERM", OsPid),
+ ok = kill("TERM", OsPid),
+ Msgs1 = fetch_msgs(Pid1),
+ io:format("Msgs1: ~p~n", [Msgs1]),
+ [{notify,sigterm},
+ {notify,sigterm},
+ {notify,sigterm}] = Msgs1,
+ %% no proc
+ ok = kill("TERM", OsPid),
+ ok = kill("TERM", OsPid),
+ ok = kill("TERM", OsPid),
+ %% ignore
+ Pid2 = setup_service(),
+ erts_internal:set_signal(sigterm, ignore),
+ ok = kill("TERM", OsPid),
+ ok = kill("TERM", OsPid),
+ ok = kill("TERM", OsPid),
+ Msgs2 = fetch_msgs(Pid2),
+ io:format("Msgs2: ~p~n", [Msgs2]),
+ [] = Msgs2,
+ %% reset to handle (it's the default)
+ erts_internal:set_signal(sigterm, handle),
+ ok.
+
+t_sigchld(_Config) ->
+ Pid1 = setup_service(),
+ OsPid = os:getpid(),
+ erts_internal:set_signal(sigchld, handle),
+ ok = kill("CHLD", OsPid),
+ ok = kill("CHLD", OsPid),
+ ok = kill("CHLD", OsPid),
+ Msgs1 = fetch_msgs(Pid1),
+ io:format("Msgs1: ~p~n", [Msgs1]),
+ [{notify,sigchld},
+ {notify,sigchld},
+ {notify,sigchld}] = Msgs1,
+ %% no proc
+ ok = kill("CHLD", OsPid),
+ ok = kill("CHLD", OsPid),
+ ok = kill("CHLD", OsPid),
+ %% ignore
+ Pid2 = setup_service(),
+ erts_internal:set_signal(sigchld, ignore),
+ ok = kill("CHLD", OsPid),
+ ok = kill("CHLD", OsPid),
+ ok = kill("CHLD", OsPid),
+ Msgs2 = fetch_msgs(Pid2),
+ io:format("Msgs2: ~p~n", [Msgs2]),
+ [] = Msgs2,
+ %% reset to handle (it's the default)
+ erts_internal:set_signal(sigchld, ignore),
+ ok.
+
+
+t_sigalrm(_Config) ->
+ Pid1 = setup_service(),
+ true = erts_internal:set_signal(sigalrm, handle),
+ ok = os_signal_SUITE:set_alarm(1),
+ receive after 3000 -> ok end,
+ Msgs1 = fetch_msgs(Pid1),
+ [{notify,sigalrm}] = Msgs1,
+ io:format("Msgs1: ~p~n", [Msgs1]),
+ erts_internal:set_signal(sigalrm, ignore),
+ Pid2 = setup_service(),
+ ok = os_signal_SUITE:set_alarm(1),
+ receive after 3000 -> ok end,
+ Msgs2 = fetch_msgs(Pid2),
+ [] = Msgs2,
+ io:format("Msgs2: ~p~n", [Msgs2]),
+ Pid3 = setup_service(),
+ erts_internal:set_signal(sigalrm, handle),
+ ok = os_signal_SUITE:set_alarm(1),
+ receive after 3000 -> ok end,
+ Msgs3 = fetch_msgs(Pid3),
+ [{notify,sigalrm}] = Msgs3,
+ io:format("Msgs3: ~p~n", [Msgs3]),
+ erts_internal:set_signal(sigalrm, ignore),
+ ok.
+
+t_sigchld_fork(_Config) ->
+ Pid1 = setup_service(),
+ true = erts_internal:set_signal(sigchld, handle),
+ {ok,OsPid} = os_signal_SUITE:fork(),
+ receive after 3000 -> ok end,
+ Msgs1 = fetch_msgs(Pid1),
+ io:format("Msgs1: ~p~n", [Msgs1]),
+ [{notify,sigchld}] = Msgs1,
+ {ok,Status} = os_signal_SUITE:get_exit_code(OsPid),
+ io:format("exit status from ~w : ~w~n", [OsPid,Status]),
+ 42 = Status,
+ %% reset to ignore (it's the default)
+ erts_internal:set_signal(sigchld, ignore),
+ ok.
+
+
+%% nif stubs
+
+set_alarm(_Secs) -> no.
+fork() -> no.
+get_exit_code(_OsPid) -> no.
+
+%% aux
+
+setup_service() ->
+ Pid = spawn_link(fun msgs/0),
+ true = erlang:register(?signal_server, Pid),
+ Pid.
+
+msgs() ->
+ msgs([]).
+msgs(Ms) ->
+ receive
+ {Pid, fetch_msgs} -> Pid ! {self(), lists:reverse(Ms)};
+ Msg ->
+ msgs([Msg|Ms])
+ end.
+
+fetch_msgs(Pid) ->
+ Pid ! {self(), fetch_msgs},
+ receive {Pid, Msgs} -> Msgs end.
+
+kill(Signal, Pid) ->
+ {0,_} = run("kill", ["-s", Signal, Pid]),
+ receive after 200 -> ok end,
+ ok.
+
+load_nif(Config) ->
+ Path = proplists:get_value(data_dir, Config),
+ ok = erlang:load_nif(filename:join(Path,"os_signal_nif"), 0).
+
+run(Program0, Args) -> run(".", Program0, Args).
+run(Cwd, Program0, Args) when is_list(Cwd) ->
+ Program = case os:find_executable(Program0) of
+ Path when is_list(Path) ->
+ Path;
+ false ->
+ exit(no)
+ end,
+ Options = [{args,Args},binary,exit_status,stderr_to_stdout,
+ {line,4096}, {cd, Cwd}],
+ try open_port({spawn_executable,Program}, Options) of
+ Port ->
+ run_loop(Port, [])
+ catch
+ error:_ ->
+ exit(no)
+ end.
+
+run_loop(Port, Output) ->
+ receive
+ {Port,{exit_status,Status}} ->
+ {Status,lists:reverse(Output)};
+ {Port,{data,{eol,Bin}}} ->
+ run_loop(Port, [Bin|Output]);
+ _Msg ->
+ run_loop(Port, Output)
+ end.
diff --git a/erts/emulator/test/os_signal_SUITE_data/Makefile.src b/erts/emulator/test/os_signal_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..a7f5cdbba5
--- /dev/null
+++ b/erts/emulator/test/os_signal_SUITE_data/Makefile.src
@@ -0,0 +1,6 @@
+
+NIF_LIBS = os_signal_nif@dll@
+
+all: $(NIF_LIBS)
+
+@SHLIB_RULES@
diff --git a/erts/emulator/test/os_signal_SUITE_data/os_signal_nif.c b/erts/emulator/test/os_signal_SUITE_data/os_signal_nif.c
new file mode 100644
index 0000000000..78e1348383
--- /dev/null
+++ b/erts/emulator/test/os_signal_SUITE_data/os_signal_nif.c
@@ -0,0 +1,66 @@
+#include
+#include
+#include
+#include
+
+#include
+
+static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ return 0;
+}
+
+static ERL_NIF_TERM set_alarm(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ int t;
+ if (!enif_get_int(env, argv[0], &t)) {
+ return enif_make_badarg(env);
+ }
+
+ alarm(t);
+
+ return enif_make_atom(env, "ok");
+}
+
+static ERL_NIF_TERM fork_0(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ pid_t pid;
+
+ pid = fork();
+
+ if (pid == 0) {
+ /* child */
+ exit(42);
+ }
+
+ return enif_make_tuple(env, 2,
+ enif_make_atom(env, "ok"),
+ enif_make_int(env, (int)pid));
+}
+
+static ERL_NIF_TERM get_exit_code(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ int x;
+ pid_t pid;
+ if (!enif_get_int(env, argv[0], &x)) {
+ return enif_make_badarg(env);
+ }
+
+ pid = (pid_t) x;
+
+ waitpid(pid, &x, 0);
+
+ return enif_make_tuple(env, 2,
+ enif_make_atom(env, "ok"),
+ enif_make_int(env, WEXITSTATUS(x)));
+}
+
+
+static ErlNifFunc nif_funcs[] =
+{
+ {"set_alarm", 1, set_alarm},
+ {"fork", 0, fork_0},
+ {"get_exit_code", 1, get_exit_code}
+};
+
+ERL_NIF_INIT(os_signal_SUITE,nif_funcs,load,NULL,NULL,NULL)
--
cgit v1.2.3
From 120f04387ade07ef5b8b6d20a04de7d21e0c40ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Thu, 5 Jan 2017 17:17:52 +0100
Subject: erts: Use generic signal handler
---
erts/emulator/beam/atom.names | 14 +-
erts/emulator/beam/bif.c | 14 +-
erts/emulator/beam/bif.tab | 1 +
erts/emulator/beam/global.h | 3 +
erts/emulator/sys/unix/sys.c | 251 ++++++++++++++++++----------------
erts/emulator/sys/win32/sys.c | 4 +
lib/kernel/src/erl_signal_handler.erl | 3 +
7 files changed, 168 insertions(+), 122 deletions(-)
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 668abfaaee..72a7b9e312 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -194,6 +194,7 @@ atom current_stacktrace
atom data
atom debug_flags
atom decimals
+atom default
atom delay_trap
atom dexit
atom depth
@@ -306,6 +307,7 @@ atom global
atom Gt='>'
atom grun
atom group_leader
+atom handle
atom have_dt_utag
atom heap_block_size
atom heap_size
@@ -566,7 +568,7 @@ atom running_procs
atom runtime
atom safe
atom save_calls
-atom scheduler
+atom scheduler
atom scheduler_id
atom schedulers_online
atom scheme
@@ -594,6 +596,16 @@ atom shared
atom sighup
atom sigterm
atom sigusr1
+atom sigusr2
+atom sigill
+atom sigchld
+atom sigabrt
+atom sigalrm
+atom sigstop
+atom sigint
+atom sigsegv
+atom sigtstp
+atom sigquit
atom silent
atom size
atom sl_alloc
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index d886c2985e..452bfef71a 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -5273,7 +5273,7 @@ BIF_RETTYPE dt_restore_tag_1(BIF_ALIST_1)
SEQ_TRACE_TOKEN(BIF_P) = am_have_dt_utag;
}
}
-#else
+#else
if (BIF_ARG_1 != am_true) {
BIF_ERROR(BIF_P,BADARG);
}
@@ -5281,4 +5281,16 @@ BIF_RETTYPE dt_restore_tag_1(BIF_ALIST_1)
BIF_RET(am_true);
}
+BIF_RETTYPE erts_internal_set_signal_2(BIF_ALIST_2) {
+ if (is_atom(BIF_ARG_1) && ((BIF_ARG_2 == am_ignore) ||
+ (BIF_ARG_2 == am_default) ||
+ (BIF_ARG_2 == am_handle))) {
+ if (!erts_set_signal(BIF_ARG_1, BIF_ARG_2))
+ goto error;
+
+ BIF_RET(am_true);
+ }
+error:
+ BIF_ERROR(BIF_P, BADARG);
+}
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 32600f4338..318a4fd264 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -668,6 +668,7 @@ gcbif erlang:ceil/1
bif math:floor/1
bif math:ceil/1
bif math:fmod/2
+bif erts_internal:set_signal/2
#
# Obsolete
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 2b2f3c5cdc..f0f959e97a 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -1070,6 +1070,9 @@ void print_process_info(fmtfn_t, void *, Process*);
void info(fmtfn_t, void *);
void loaded(fmtfn_t, void *);
+/* sighandler sys.c */
+int erts_set_signal(Eterm signal, Eterm type);
+
/* erl_arith.c */
double erts_get_positive_zero_float(void);
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index de9c1b2ca0..4175dc6a41 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -107,7 +107,7 @@ static volatile int have_prepared_crash_dump;
erts_smp_atomic_t sys_misc_mem_sz;
#if defined(ERTS_SMP)
-static void smp_sig_notify(char c);
+static void smp_sig_notify(int signum);
static int sig_notify_fds[2] = {-1, -1};
#if !defined(ETHR_UNUSABLE_SIGUSRX) && defined(ERTS_THR_HAVE_SIG_FUNCS)
@@ -395,14 +395,6 @@ erts_sys_pre_init(void)
/* After creation in parent */
eid.thread_create_parent_func = thr_create_cleanup,
-#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, SIGHUP); /* block sighups */
- sigaddset(&thr_create_sigmask, SIGUSR1); /* block user defined signal */
-#endif
-
erts_thr_init(&eid);
#ifdef ERTS_ENABLE_LOCK_CHECK
@@ -654,33 +646,15 @@ break_requested(void)
ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */
}
-/* set up signal handlers for break and quit */
-#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
-static RETSIGTYPE request_break(void)
-#else
static RETSIGTYPE request_break(int signum)
-#endif
{
#ifdef ERTS_SMP
- smp_sig_notify('I');
+ smp_sig_notify(signum);
#else
break_requested();
#endif
}
-#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('T');
-#else
- signal_notify_requested(am_sigterm);
-#endif
-}
-
#ifdef ETHR_UNUSABLE_SIGUSRX
#warning "Unusable SIGUSR1 & SIGUSR2. Disabling use of these signals"
@@ -701,19 +675,6 @@ sys_thr_resume(erts_tid_t tid) {
}
#endif
-#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
-static RETSIGTYPE user_signal1(void)
-#else
-static RETSIGTYPE user_signal1(int signum)
-#endif
-{
-#ifdef ERTS_SMP
- smp_sig_notify('1');
-#else
- signal_notify_requested(am_sigusr1);
-#endif
-}
-
#ifdef ERTS_SYS_SUSPEND_SIGNAL
#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
static RETSIGTYPE suspend_signal(void)
@@ -733,43 +694,101 @@ static RETSIGTYPE suspend_signal(int signum)
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
-static void
-quit_requested(void)
+/*
+ Signal Action Comment
+ ─────────────────────────────────────────────────────────────
+ SIGHUP Term Hangup detected on controlling terminal or death of controlling process
+ SIGINT Term Interrupt from keyboard
+ SIGQUIT Core Quit from keyboard
+ SIGILL Core Illegal Instruction
+ SIGABRT Core Abort signal from abort(3)
+ !SIGFPE Core Floating point exception
+ !SIGKILL Term Kill signal
+ !SIGSEGV Core Invalid memory reference
+ !SIGPIPE Term Broken pipe: write to pipe with no readers
+ SIGALRM Term Timer signal from alarm(2)
+ SIGTERM Term Termination signal
+ SIGUSR1 Term User-defined signal 1
+ SIGUSR2 Term User-defined signal 2
+ !SIGCHLD Ign Child stopped or terminated
+ !SIGCONT Cont Continue if stopped
+ SIGSTOP Stop Stop process
+ SIGTSTP Stop Stop typed at terminal
+ !SIGTTIN Stop Terminal input for background process
+ !SIGTTOU Stop Terminal output for background process
+*/
+
+
+static ERTS_INLINE int
+signalterm_to_signum(Eterm signal)
{
- erts_exit(ERTS_INTR_EXIT, "");
+ switch (signal) {
+ case am_sighup: return SIGHUP;
+ case am_sigint: return SIGINT;
+ case am_sigquit: return SIGQUIT;
+ case am_sigill: return SIGILL;
+ case am_sigabrt: return SIGABRT;
+ /* case am_sigsegv: return SIGSEGV; */
+ case am_sigalrm: return SIGALRM;
+ case am_sigterm: return SIGTERM;
+ case am_sigusr1: return SIGUSR1;
+ case am_sigusr2: return SIGUSR2;
+ case am_sigchld: return SIGCHLD;
+ case am_sigstop: return SIGSTOP;
+ case am_sigtstp: return SIGTSTP;
+ default: return 0;
+ }
}
-#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
-static RETSIGTYPE do_quit(void)
-#else
-static RETSIGTYPE do_quit(int signum)
-#endif
+static ERTS_INLINE Eterm
+signum_to_signalterm(int signum)
{
-#ifdef ERTS_SMP
- smp_sig_notify('Q');
-#else
- quit_requested();
-#endif
+ switch (signum) {
+ case SIGHUP: return am_sighup;
+ case SIGINT: return am_sigint; /* ^c */
+ case SIGILL: return am_sigill;
+ case SIGABRT: return am_sigabrt;
+ /* case SIGSEGV: return am_sigsegv; */
+ case SIGALRM: return am_sigalrm;
+ case SIGTERM: return am_sigterm;
+ case SIGQUIT: return am_sigquit; /* ^\ */
+ case SIGUSR1: return am_sigusr1;
+ case SIGUSR2: return am_sigusr2;
+ case SIGCHLD: return am_sigchld;
+ case SIGSTOP: return am_sigstop;
+ case SIGTSTP: return am_sigtstp; /* ^z */
+ default: return am_error;
+ }
}
-#if (defined(SIG_SIGSET) || defined(SIG_SIGNAL))
-static RETSIGTYPE request_sighup(void)
-#else
-static RETSIGTYPE request_sighup(int signum)
-#endif
+static RETSIGTYPE generic_signal_handler(int signum)
{
#ifdef ERTS_SMP
- smp_sig_notify('H');
+ smp_sig_notify(signum);
#else
- signal_notify_requested(am_sighup);
+ Eterm signal = signum_to_signalterm(signum);
+ signal_notify_requested(signal);
#endif
}
+int erts_set_signal(Eterm signal, Eterm type) {
+ int signum;
+ if ((signum = signalterm_to_signum(signal)) > 0) {
+ if (type == am_ignore) {
+ sys_signal(signum, SIG_IGN);
+ } else if (type == am_default) {
+ sys_signal(signum, SIG_DFL);
+ } else {
+ sys_signal(signum, generic_signal_handler);
+ }
+ return 1;
+ }
+ return 0;
+}
+
/* Disable break */
void erts_set_ignore_break(void) {
sys_signal(SIGINT, SIG_IGN);
- sys_signal(SIGTERM, SIG_IGN);
- sys_signal(SIGHUP, SIG_IGN);
sys_signal(SIGQUIT, SIG_IGN);
sys_signal(SIGTSTP, SIG_IGN);
}
@@ -794,13 +813,13 @@ void erts_replace_intr(void) {
void init_break_handler(void)
{
- sys_signal(SIGINT, request_break);
- sys_signal(SIGTERM, request_stop);
- sys_signal(SIGHUP, request_sighup);
+ sys_signal(SIGINT, request_break);
+ sys_signal(SIGTERM, generic_signal_handler);
+ sys_signal(SIGHUP, generic_signal_handler);
#ifndef ETHR_UNUSABLE_SIGUSRX
- sys_signal(SIGUSR1, user_signal1);
+ sys_signal(SIGUSR1, generic_signal_handler);
#endif /* #ifndef ETHR_UNUSABLE_SIGUSRX */
- sys_signal(SIGQUIT, do_quit);
+ sys_signal(SIGQUIT, generic_signal_handler);
}
void sys_init_suspend_handler(void)
@@ -1216,14 +1235,14 @@ erl_sys_schedule(int runnable)
static erts_smp_tid_t sig_dispatcher_tid;
static void
-smp_sig_notify(char c)
+smp_sig_notify(int signum)
{
int res;
do {
/* write() is async-signal safe (according to posix) */
- res = write(sig_notify_fds[1], &c, 1);
+ res = write(sig_notify_fds[1], &signum, sizeof(int));
} while (res < 0 && errno == EINTR);
- if (res != 1) {
+ if (res != sizeof(int)) {
char msg[] =
"smp_sig_notify(): Failed to notify signal-dispatcher thread "
"about received signal";
@@ -1239,63 +1258,55 @@ signal_dispatcher_thread_func(void *unused)
erts_lc_set_thread_name("signal_dispatcher");
#endif
while (1) {
- char buf[32];
- int res, i;
+ union {int signum; char buf[4];} sb;
+ Eterm signal;
+ int res, i = 0;
/* Block on read() waiting for a signal notification to arrive... */
- res = read(sig_notify_fds[0], (void *) &buf[0], 32);
+
+ do {
+ res = read(sig_notify_fds[0], (void *) &sb.buf[i], sizeof(int) - i);
+ i += res;
+ } while ((i != sizeof(int) && res >= 0) || (res < 0 && errno == EINTR));
+
if (res < 0) {
- if (errno == EINTR)
- continue;
erts_exit(ERTS_ABORT_EXIT,
"signal-dispatcher thread got unexpected error: %s (%d)\n",
erl_errno_id(errno),
errno);
}
- for (i = 0; i < res; i++) {
- /*
- * NOTE 1: The signal dispatcher thread should not do work
- * that takes a substantial amount of time (except
- * perhaps in test and debug builds). It needs to
- * be responsive, i.e, it should only dispatch work
- * to other threads.
- *
- * NOTE 2: The signal dispatcher thread is not a blockable
- * thread (i.e., not a thread managed by the
- * erl_thr_progress module). This is intentional.
- * We want to be able to interrupt writing of a crash
- * dump by hitting C-c twice. Since it isn't a
- * blockable thread it is important that it doesn't
- * change the state of any data that a blocking thread
- * expects to have exclusive access to (unless the
- * signal dispatcher itself explicitly is blocking all
- * blockable threads).
- */
- switch (buf[i]) {
- case 0: /* Emulator initialized */
- break;
- case 'H': /* SIGHUP */
- signal_notify_requested(am_sighup);
+ /*
+ * NOTE 1: The signal dispatcher thread should not do work
+ * that takes a substantial amount of time (except
+ * perhaps in test and debug builds). It needs to
+ * be responsive, i.e, it should only dispatch work
+ * to other threads.
+ *
+ * NOTE 2: The signal dispatcher thread is not a blockable
+ * thread (i.e., not a thread managed by the
+ * erl_thr_progress module). This is intentional.
+ * We want to be able to interrupt writing of a crash
+ * dump by hitting C-c twice. Since it isn't a
+ * blockable thread it is important that it doesn't
+ * change the state of any data that a blocking thread
+ * expects to have exclusive access to (unless the
+ * signal dispatcher itself explicitly is blocking all
+ * blockable threads).
+ */
+ switch (sb.signum) {
+ case 0: continue;
+ case SIGINT:
+ break_requested();
break;
- case 'T': /* SIGTERM */
- signal_notify_requested(am_sigterm);
- break;
- case '1': /* SIGUSR1 */
- signal_notify_requested(am_sigusr1);
- break;
- case 'I': /* SIGINT */
- break_requested();
- break;
- case 'Q': /* SIGQUIT */
- quit_requested();
- break;
- default:
- erts_exit(ERTS_ABORT_EXIT,
- "signal-dispatcher thread received unknown "
- "signal notification: '%c'\n",
- buf[i]);
- }
- }
- ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
+ default:
+ if ((signal = signum_to_signalterm(sb.signum)) == am_error) {
+ erts_exit(ERTS_ABORT_EXIT,
+ "signal-dispatcher thread received unknown "
+ "signal notification: '%d'\n",
+ sb.signum);
+ }
+ signal_notify_requested(signal);
+ }
+ ERTS_SMP_LC_ASSERT(!erts_thr_progress_is_blocking());
}
return NULL;
}
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index f3881e0736..408b4f47ab 100644
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -294,6 +294,10 @@ int erts_sys_prepare_crash_dump(int secs)
return 0;
}
+int erts_set_signal(Eterm signal, Eterm type) {
+ return 0;
+}
+
static void
init_console(void)
{
diff --git a/lib/kernel/src/erl_signal_handler.erl b/lib/kernel/src/erl_signal_handler.erl
index 43cc307ffd..8f924d2adc 100644
--- a/lib/kernel/src/erl_signal_handler.erl
+++ b/lib/kernel/src/erl_signal_handler.erl
@@ -31,6 +31,9 @@ init(_Args) ->
handle_event(sigusr1, S) ->
erlang:halt("Received SIGUSR1"),
{ok, S};
+handle_event(sigquit, S) ->
+ erlang:halt(),
+ {ok, S};
handle_event(sigterm, S) ->
error_logger:info_msg("SIGTERM received - shutting down~n"),
ok = init:stop(),
--
cgit v1.2.3
From d3506c8dc3d355b7a62085da508b41866e431a37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Fri, 20 Jan 2017 14:27:40 +0100
Subject: erts: Do not enable SIGINT
---
erts/emulator/sys/unix/sys.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 4175dc6a41..ce87e3c7a6 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -698,7 +698,7 @@ static RETSIGTYPE suspend_signal(int signum)
Signal Action Comment
─────────────────────────────────────────────────────────────
SIGHUP Term Hangup detected on controlling terminal or death of controlling process
- SIGINT Term Interrupt from keyboard
+ !SIGINT Term Interrupt from keyboard
SIGQUIT Core Quit from keyboard
SIGILL Core Illegal Instruction
SIGABRT Core Abort signal from abort(3)
@@ -724,7 +724,7 @@ signalterm_to_signum(Eterm signal)
{
switch (signal) {
case am_sighup: return SIGHUP;
- case am_sigint: return SIGINT;
+ /* case am_sigint: return SIGINT; */
case am_sigquit: return SIGQUIT;
case am_sigill: return SIGILL;
case am_sigabrt: return SIGABRT;
@@ -745,7 +745,7 @@ signum_to_signalterm(int signum)
{
switch (signum) {
case SIGHUP: return am_sighup;
- case SIGINT: return am_sigint; /* ^c */
+ /* case SIGINT: return am_sigint; */ /* ^c */
case SIGILL: return am_sigill;
case SIGABRT: return am_sigabrt;
/* case SIGSEGV: return am_sigsegv; */
--
cgit v1.2.3
From 314fddc2e2e4cd8587ce00dfce328245a315832f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Fri, 20 Jan 2017 16:28:42 +0100
Subject: erts: Fix thread suspend in crashdump
* move signal handler setup
---
erts/emulator/beam/break.c | 2 ++
erts/emulator/beam/erl_init.c | 1 -
erts/emulator/beam/sys.h | 3 +++
erts/emulator/sys/unix/sys.c | 3 +--
4 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 6e1e94b95b..2fc61ab436 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -717,6 +717,8 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
* We have to be very very careful when doing this as the schedulers
* could be anywhere.
*/
+ sys_init_suspend_handler();
+
for (i = 0; i < erts_no_schedulers; i++) {
erts_tid_t tid = ERTS_SCHEDULER_IX(i)->tid;
if (!erts_equal_tids(tid,erts_thr_self()))
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index c5904b375e..88bd002a8c 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -2220,7 +2220,6 @@ erl_start(int argc, char **argv)
init_break_handler();
if (replace_intr)
erts_replace_intr();
- sys_init_suspend_handler();
#endif
boot_argc = argc - i; /* Number of arguments to init */
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index ceea794cc4..a11fb16b39 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -851,9 +851,12 @@ int erts_sys_unsetenv(char *key);
char *erts_read_env(char *key);
void erts_free_read_env(void *value);
+#if defined(ERTS_SMP)
#if defined(ERTS_THR_HAVE_SIG_FUNCS) && !defined(ETHR_UNUSABLE_SIGUSRX)
extern void sys_thr_resume(erts_tid_t tid);
extern void sys_thr_suspend(erts_tid_t tid);
+#define ERTS_SYS_SUSPEND_SIGNAL SIGUSR2
+#endif
#endif
/* utils.c */
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index ce87e3c7a6..a25d865c91 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -110,9 +110,8 @@ erts_smp_atomic_t sys_misc_mem_sz;
static void smp_sig_notify(int signum);
static int sig_notify_fds[2] = {-1, -1};
-#if !defined(ETHR_UNUSABLE_SIGUSRX) && defined(ERTS_THR_HAVE_SIG_FUNCS)
+#ifdef ERTS_SYS_SUSPEND_SIGNAL
static int sig_suspend_fds[2] = {-1, -1};
-#define ERTS_SYS_SUSPEND_SIGNAL SIGUSR2
#endif
#endif
--
cgit v1.2.3
From 9ccb988eeb79815a33e0dd138278e0c29ed3ca6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Mon, 23 Jan 2017 16:05:07 +0100
Subject: erts: Do not handle SIGILL
* Remove SIGILL from signal whitelist
---
erts/emulator/sys/unix/sys.c | 8 ++++----
erts/emulator/test/os_signal_SUITE.erl | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index a25d865c91..cb20c690b4 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -699,7 +699,7 @@ static RETSIGTYPE suspend_signal(int signum)
SIGHUP Term Hangup detected on controlling terminal or death of controlling process
!SIGINT Term Interrupt from keyboard
SIGQUIT Core Quit from keyboard
- SIGILL Core Illegal Instruction
+ !SIGILL Core Illegal Instruction
SIGABRT Core Abort signal from abort(3)
!SIGFPE Core Floating point exception
!SIGKILL Term Kill signal
@@ -725,7 +725,7 @@ signalterm_to_signum(Eterm signal)
case am_sighup: return SIGHUP;
/* case am_sigint: return SIGINT; */
case am_sigquit: return SIGQUIT;
- case am_sigill: return SIGILL;
+ /* case am_sigill: return SIGILL; */
case am_sigabrt: return SIGABRT;
/* case am_sigsegv: return SIGSEGV; */
case am_sigalrm: return SIGALRM;
@@ -745,12 +745,12 @@ signum_to_signalterm(int signum)
switch (signum) {
case SIGHUP: return am_sighup;
/* case SIGINT: return am_sigint; */ /* ^c */
- case SIGILL: return am_sigill;
+ case SIGQUIT: return am_sigquit; /* ^\ */
+ /* case SIGILL: return am_sigill; */
case SIGABRT: return am_sigabrt;
/* case SIGSEGV: return am_sigsegv; */
case SIGALRM: return am_sigalrm;
case SIGTERM: return am_sigterm;
- case SIGQUIT: return am_sigquit; /* ^\ */
case SIGUSR1: return am_sigusr1;
case SIGUSR2: return am_sigusr2;
case SIGCHLD: return am_sigchld;
diff --git a/erts/emulator/test/os_signal_SUITE.erl b/erts/emulator/test/os_signal_SUITE.erl
index 2b9343663d..7c3950114f 100644
--- a/erts/emulator/test/os_signal_SUITE.erl
+++ b/erts/emulator/test/os_signal_SUITE.erl
@@ -86,7 +86,7 @@ end_per_suite(_Config) ->
set_unset(_Config) ->
Signals = [sighup, %sigint,
- sigquit, sigill,
+ sigquit, %sigill,
sigabrt,
sigalrm, sigterm,
sigusr1, sigusr2,
--
cgit v1.2.3
From d4bd17da9759af54227891a90d9fb83d5bfe6d7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Tue, 24 Jan 2017 10:59:30 +0100
Subject: erts: Use os module instead of erts_internal for set_signal/2
* Add specs
* Change return signature to 'ok' instead of 'true'
---
erts/emulator/beam/bif.c | 14 ----------
erts/emulator/beam/bif.tab | 2 +-
erts/emulator/beam/erl_bif_os.c | 14 ++++++++++
erts/emulator/test/os_signal_SUITE.erl | 48 +++++++++++++++++-----------------
lib/kernel/src/os.erl | 11 +++++++-
5 files changed, 49 insertions(+), 40 deletions(-)
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 452bfef71a..1048300cf7 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -5280,17 +5280,3 @@ BIF_RETTYPE dt_restore_tag_1(BIF_ALIST_1)
#endif
BIF_RET(am_true);
}
-
-BIF_RETTYPE erts_internal_set_signal_2(BIF_ALIST_2) {
- if (is_atom(BIF_ARG_1) && ((BIF_ARG_2 == am_ignore) ||
- (BIF_ARG_2 == am_default) ||
- (BIF_ARG_2 == am_handle))) {
- if (!erts_set_signal(BIF_ARG_1, BIF_ARG_2))
- goto error;
-
- BIF_RET(am_true);
- }
-
-error:
- BIF_ERROR(BIF_P, BADARG);
-}
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 318a4fd264..f90fae6041 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -668,7 +668,7 @@ gcbif erlang:ceil/1
bif math:floor/1
bif math:ceil/1
bif math:fmod/2
-bif erts_internal:set_signal/2
+bif os:set_signal/2
#
# Obsolete
diff --git a/erts/emulator/beam/erl_bif_os.c b/erts/emulator/beam/erl_bif_os.c
index 46777d3aa5..edc3c82b23 100644
--- a/erts/emulator/beam/erl_bif_os.c
+++ b/erts/emulator/beam/erl_bif_os.c
@@ -203,3 +203,17 @@ BIF_RETTYPE os_unsetenv_1(BIF_ALIST_1)
}
BIF_RET(am_true);
}
+
+BIF_RETTYPE os_set_signal_2(BIF_ALIST_2) {
+ if (is_atom(BIF_ARG_1) && ((BIF_ARG_2 == am_ignore) ||
+ (BIF_ARG_2 == am_default) ||
+ (BIF_ARG_2 == am_handle))) {
+ if (!erts_set_signal(BIF_ARG_1, BIF_ARG_2))
+ goto error;
+
+ BIF_RET(am_ok);
+ }
+
+error:
+ BIF_ERROR(BIF_P, BADARG);
+}
diff --git a/erts/emulator/test/os_signal_SUITE.erl b/erts/emulator/test/os_signal_SUITE.erl
index 7c3950114f..9aa49a453e 100644
--- a/erts/emulator/test/os_signal_SUITE.erl
+++ b/erts/emulator/test/os_signal_SUITE.erl
@@ -92,9 +92,9 @@ set_unset(_Config) ->
sigusr1, sigusr2,
sigchld,
sigstop, sigtstp],
- F1 = fun(Sig) -> true = erts_internal:set_signal(Sig,handle) end,
- F2 = fun(Sig) -> true = erts_internal:set_signal(Sig,default) end,
- F3 = fun(Sig) -> true = erts_internal:set_signal(Sig,ignore) end,
+ F1 = fun(Sig) -> ok = os:set_signal(Sig,handle) end,
+ F2 = fun(Sig) -> ok = os:set_signal(Sig,default) end,
+ F3 = fun(Sig) -> ok = os:set_signal(Sig,ignore) end,
%% set handle
ok = lists:foreach(F1, Signals),
%% set ignore
@@ -106,7 +106,7 @@ set_unset(_Config) ->
t_sighup(_Config) ->
Pid1 = setup_service(),
OsPid = os:getpid(),
- erts_internal:set_signal(sighup, handle),
+ os:set_signal(sighup, handle),
ok = kill("HUP", OsPid),
ok = kill("HUP", OsPid),
ok = kill("HUP", OsPid),
@@ -121,7 +121,7 @@ t_sighup(_Config) ->
ok = kill("HUP", OsPid),
%% ignore
Pid2 = setup_service(),
- erts_internal:set_signal(sighup, ignore),
+ os:set_signal(sighup, ignore),
ok = kill("HUP", OsPid),
ok = kill("HUP", OsPid),
ok = kill("HUP", OsPid),
@@ -129,13 +129,13 @@ t_sighup(_Config) ->
io:format("Msgs2: ~p~n", [Msgs2]),
[] = Msgs2,
%% reset to handle (it's the default)
- erts_internal:set_signal(sighup, handle),
+ os:set_signal(sighup, handle),
ok.
t_sigusr1(_Config) ->
Pid1 = setup_service(),
OsPid = os:getpid(),
- erts_internal:set_signal(sigusr1, handle),
+ os:set_signal(sigusr1, handle),
ok = kill("USR1", OsPid),
ok = kill("USR1", OsPid),
ok = kill("USR1", OsPid),
@@ -150,7 +150,7 @@ t_sigusr1(_Config) ->
ok = kill("USR1", OsPid),
%% ignore
Pid2 = setup_service(),
- erts_internal:set_signal(sigusr1, ignore),
+ os:set_signal(sigusr1, ignore),
ok = kill("USR1", OsPid),
ok = kill("USR1", OsPid),
ok = kill("USR1", OsPid),
@@ -158,13 +158,13 @@ t_sigusr1(_Config) ->
io:format("Msgs2: ~p~n", [Msgs2]),
[] = Msgs2,
%% reset to ignore (it's the default)
- erts_internal:set_signal(sigusr1, handle),
+ os:set_signal(sigusr1, handle),
ok.
t_sigusr2(_Config) ->
Pid1 = setup_service(),
OsPid = os:getpid(),
- erts_internal:set_signal(sigusr2, handle),
+ os:set_signal(sigusr2, handle),
ok = kill("USR2", OsPid),
ok = kill("USR2", OsPid),
ok = kill("USR2", OsPid),
@@ -179,7 +179,7 @@ t_sigusr2(_Config) ->
ok = kill("USR2", OsPid),
%% ignore
Pid2 = setup_service(),
- erts_internal:set_signal(sigusr2, ignore),
+ os:set_signal(sigusr2, ignore),
ok = kill("USR2", OsPid),
ok = kill("USR2", OsPid),
ok = kill("USR2", OsPid),
@@ -187,13 +187,13 @@ t_sigusr2(_Config) ->
io:format("Msgs2: ~p~n", [Msgs2]),
[] = Msgs2,
%% reset to ignore (it's the default)
- erts_internal:set_signal(sigusr2, ignore),
+ os:set_signal(sigusr2, ignore),
ok.
t_sigterm(_Config) ->
Pid1 = setup_service(),
OsPid = os:getpid(),
- erts_internal:set_signal(sigterm, handle),
+ os:set_signal(sigterm, handle),
ok = kill("TERM", OsPid),
ok = kill("TERM", OsPid),
ok = kill("TERM", OsPid),
@@ -208,7 +208,7 @@ t_sigterm(_Config) ->
ok = kill("TERM", OsPid),
%% ignore
Pid2 = setup_service(),
- erts_internal:set_signal(sigterm, ignore),
+ os:set_signal(sigterm, ignore),
ok = kill("TERM", OsPid),
ok = kill("TERM", OsPid),
ok = kill("TERM", OsPid),
@@ -216,13 +216,13 @@ t_sigterm(_Config) ->
io:format("Msgs2: ~p~n", [Msgs2]),
[] = Msgs2,
%% reset to handle (it's the default)
- erts_internal:set_signal(sigterm, handle),
+ os:set_signal(sigterm, handle),
ok.
t_sigchld(_Config) ->
Pid1 = setup_service(),
OsPid = os:getpid(),
- erts_internal:set_signal(sigchld, handle),
+ os:set_signal(sigchld, handle),
ok = kill("CHLD", OsPid),
ok = kill("CHLD", OsPid),
ok = kill("CHLD", OsPid),
@@ -237,7 +237,7 @@ t_sigchld(_Config) ->
ok = kill("CHLD", OsPid),
%% ignore
Pid2 = setup_service(),
- erts_internal:set_signal(sigchld, ignore),
+ os:set_signal(sigchld, ignore),
ok = kill("CHLD", OsPid),
ok = kill("CHLD", OsPid),
ok = kill("CHLD", OsPid),
@@ -245,19 +245,19 @@ t_sigchld(_Config) ->
io:format("Msgs2: ~p~n", [Msgs2]),
[] = Msgs2,
%% reset to handle (it's the default)
- erts_internal:set_signal(sigchld, ignore),
+ os:set_signal(sigchld, ignore),
ok.
t_sigalrm(_Config) ->
Pid1 = setup_service(),
- true = erts_internal:set_signal(sigalrm, handle),
+ ok = os:set_signal(sigalrm, handle),
ok = os_signal_SUITE:set_alarm(1),
receive after 3000 -> ok end,
Msgs1 = fetch_msgs(Pid1),
[{notify,sigalrm}] = Msgs1,
io:format("Msgs1: ~p~n", [Msgs1]),
- erts_internal:set_signal(sigalrm, ignore),
+ os:set_signal(sigalrm, ignore),
Pid2 = setup_service(),
ok = os_signal_SUITE:set_alarm(1),
receive after 3000 -> ok end,
@@ -265,18 +265,18 @@ t_sigalrm(_Config) ->
[] = Msgs2,
io:format("Msgs2: ~p~n", [Msgs2]),
Pid3 = setup_service(),
- erts_internal:set_signal(sigalrm, handle),
+ os:set_signal(sigalrm, handle),
ok = os_signal_SUITE:set_alarm(1),
receive after 3000 -> ok end,
Msgs3 = fetch_msgs(Pid3),
[{notify,sigalrm}] = Msgs3,
io:format("Msgs3: ~p~n", [Msgs3]),
- erts_internal:set_signal(sigalrm, ignore),
+ os:set_signal(sigalrm, ignore),
ok.
t_sigchld_fork(_Config) ->
Pid1 = setup_service(),
- true = erts_internal:set_signal(sigchld, handle),
+ ok = os:set_signal(sigchld, handle),
{ok,OsPid} = os_signal_SUITE:fork(),
receive after 3000 -> ok end,
Msgs1 = fetch_msgs(Pid1),
@@ -286,7 +286,7 @@ t_sigchld_fork(_Config) ->
io:format("exit status from ~w : ~w~n", [OsPid,Status]),
42 = Status,
%% reset to ignore (it's the default)
- erts_internal:set_signal(sigchld, ignore),
+ os:set_signal(sigchld, ignore),
ok.
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index f8519d3a5e..c3ffcb3f70 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -29,7 +29,7 @@
-export([getenv/0, getenv/1, getenv/2, getpid/0,
perf_counter/0, perf_counter/1,
- putenv/2, system_time/0, system_time/1,
+ putenv/2, set_signal/2, system_time/0, system_time/1,
timestamp/0, unsetenv/1]).
-spec getenv() -> [string()].
@@ -104,6 +104,15 @@ timestamp() ->
unsetenv(_) ->
erlang:nif_error(undef).
+-spec set_signal(Signal, Option) -> 'ok' when
+ Signal :: 'sighup' | 'sigquit' | 'sigabrt' | 'sigalrm' |
+ 'sigterm' | 'sigusr1' | 'sigusr2' | 'sigchld' |
+ 'sigstop' | 'sigtstp',
+ Option :: 'default' | 'handle' | 'ignore'.
+
+set_signal(_Signal, _Option) ->
+ erlang:nif_error(undef).
+
%%% End of BIFs
-spec type() -> {Osfamily, Osname} when
--
cgit v1.2.3
From 1409b6ae110f60c410e83d1923dd59ae3659a887 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?=
Date: Wed, 1 Feb 2017 16:44:50 +0100
Subject: kernel: Document signal server
---
lib/kernel/doc/src/kernel_app.xml | 59 +++++++++++++++++++++++++++++++++++++--
lib/kernel/doc/src/os.xml | 31 ++++++++++++++++++--
2 files changed, 84 insertions(+), 6 deletions(-)
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index df681a505f..c581fa9d1e 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -11,7 +11,7 @@
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -19,7 +19,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
+
kernel
@@ -57,6 +57,60 @@
error_logger(3).
+
+ OS Signal Event Handler
+ Asynchronous OS signals may be subscribed to via the Kernel applications event manager
+ (see OTP Design Principles and
+ gen_event(3)) registered as erl_signal_server.
+ A default signal handler is installed which handles the following signals:
+
+ sigusr1
+ The default handler will halt Erlang and produce a crashdump
+ with slogan "Received SIGUSR1".
+ This is equivalent to calling erlang:halt("Received SIGUSR1").
+
+
+ sigquit
+ The default handler will halt Erlang immediately.
+ This is equivalent to calling erlang:halt().
+
+
+ sigterm
+ The default handler will terminate Erlang normally.
+ This is equivalent to calling init:stop().
+
+
+
+
+ Events
+ Any event handler added to erl_signal_server must handle the following events.
+
+ sighup
+ Hangup detected on controlling terminal or death of controlling process
+ sigquit
+ Quit from keyboard
+ sigabrt
+ Abort signal from abort
+ sigalrm
+ Timer signal from alarm
+ sigterm
+ Termination signal
+ sigusr1
+ User-defined signal 1
+ sigusr2
+ User-defined signal 2
+ sigchld
+ Child process stopped or terminated
+ sigstop
+ Stop process
+ sigtstp
+ Stop typed at terminal
+
+
+ Setting OS signals are described in os:set_signal/2.
+
+
+
Configuration
The following configuration parameters are defined for the Kernel
@@ -405,4 +459,3 @@ MaxT = TickTime + TickTime / 4
timer(3)
-
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 739ac35d2a..6ba69d12a3 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -11,7 +11,7 @@
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
@@ -19,7 +19,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-
+
os
@@ -155,6 +155,32 @@ DirOut = os:cmd("dir"), % on Win32 platform
+
+
+ Enables or disables handling of OS signals.
+
+ Enables or disables OS signals.
+ Each signal my be set to one of the following options:
+
+ ignore
+ -
+ This signal will be ignored.
+
+
+ default
+ -
+ This signal will use the default signal handler for the operating system.
+
+
+ handle
+ -
+ This signal will notify erl_signal_server when it is received by
+ the Erlang runtime system.
+
+
+
+
+
Current OS system time.
@@ -296,4 +322,3 @@ calendar:now_to_universal_time(TS),
-
--
cgit v1.2.3