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