# HG changeset patch # User jbe # Date 1496772089 -7200 # Node ID d4c82c90d244ee575b27e63645f815607f519966 # Parent 4f965eda4c2fd400b749b351e907be95c53ddb4e Make moonbridge_io.signalsocket(...) return a new socket each time it is called diff -r 4f965eda4c2f -r d4c82c90d244 moonbridge_io.c --- a/moonbridge_io.c Tue Jun 06 18:00:30 2017 +0200 +++ b/moonbridge_io.c Tue Jun 06 20:01:29 2017 +0200 @@ -55,16 +55,16 @@ moonbr_io_return_prepared_errmsg(); \ } while (0) -static int moonbr_io_signalfds[2]; -#define moonbr_io_signalfd_read moonbr_io_signalfds[0] -#define moonbr_io_signalfd_write moonbr_io_signalfds[1] +#define MOONBR_IO_MAXSIGNUM 127 +static int moonbr_io_signalfds[2*(MOONBR_IO_MAXSIGNUM+1)]; +#define moonbr_io_signalfd_read(x) moonbr_io_signalfds[2*(x)+0] +#define moonbr_io_signalfd_write(x) moonbr_io_signalfds[2*(x)+1] #define MOONBR_IO_HANDLE_MT_REGKEY "moonbridge_io_handle" #define MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY "moonbridge_io_handle_public" #define MOONBR_IO_LISTENER_MT_REGKEY "moonbridge_io_listener" #define MOONBR_IO_CHILD_MT_REGKEY "moonbridge_io_child" #define MOONBR_IO_CHILD_PT_REGKEY "moonbridge_io_child_pt" -#define MOONBR_IO_SIGNALSOCKET_REGKEY "moonbridge_io_signalsocket" #define MOONBR_IO_SIGNALS_REGKEY "moonbridge_io_signals" #ifdef MOONBR_IO_USE_TLS @@ -1615,47 +1615,39 @@ static void moonbr_io_signalhandler(int sig) { int errno2 = errno; - char buf[1] = {sig}; - write(moonbr_io_signalfd_write, buf, 1); + char buf[1] = {'.'}; + write(moonbr_io_signalfd_write(sig), buf, 1); errno = errno2; } static int moonbr_io_signalsocket(lua_State *L) { - int i, argc, sig; - if (moonbr_io_signalfd_read < 0) { - if (socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, moonbr_io_signalfds)) { - luaL_error(L, "Could not create socket pair for signal queueing"); + int sig, fd; + if (lua_type(L, 1) == LUA_TSTRING) { + lua_getfield(L, LUA_REGISTRYINDEX, MOONBR_IO_SIGNALS_REGKEY); + lua_pushvalue(L, 1); + lua_gettable(L, -2); + sig = lua_tointeger(L, -1); + if (!sig) { + lua_pushvalue(L, 1); + luaL_error(L, "Unknown signal \"%s\"", lua_tostring(L, 1)); } + } else { + sig = luaL_checkinteger(L, 1); } - lua_getfield(L, LUA_REGISTRYINDEX, MOONBR_IO_SIGNALS_REGKEY); - lua_insert(L, 1); - argc = lua_gettop(L); - for (i=2; i<=argc; i++) { - if (lua_type(L, i) == LUA_TSTRING) { - lua_pushvalue(L, i); - lua_gettable(L, 1); - sig = lua_tointeger(L, -1); - lua_pop(L, 1); - if (!sig) { - lua_pushvalue(L, i); - luaL_error(L, "Unknown signal \"%s\"", lua_tostring(L, i)); - } - } else { - sig = luaL_checkinteger(L, i); + if (sig < 1 || sig > MOONBR_IO_MAXSIGNUM) { + luaL_error(L, "Signal number %i out of range", sig); + } + if (moonbr_io_signalfd_read(sig) < 0) { + if (socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, moonbr_io_signalfds+2*sig)) { + luaL_error(L, "Could not create socket pair for signal queueing"); } errno = 0; signal(sig, moonbr_io_signalhandler); - if (errno) luaL_error(L, "Could not install signal handler (invalid signal number?)"); + if (errno) luaL_error(L, "Could not install signal handler (invalid signal number %i?)", sig); } - lua_settop(L, 0); - lua_getfield(L, LUA_REGISTRYINDEX, MOONBR_IO_SIGNALSOCKET_REGKEY); - if (lua_isnil(L, -1)) { - int fd = dup(moonbr_io_signalfd_read); /* TODO: determine how mooonbr_io_pushhandle acts in case of error */ - if (fd < 0) luaL_error(L, "Error in dup() system call"); - moonbr_io_pushhandle(L, fd); - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, MOONBR_IO_SIGNALSOCKET_REGKEY); - } + fd = dup(moonbr_io_signalfd_read(sig)); + if (fd < 0) luaL_error(L, "Could not create duplicated file descriptor for signal socket"); + moonbr_io_pushhandle(L, fd); return 1; } @@ -2035,8 +2027,13 @@ int luaopen_moonbridge_io(lua_State *L) { signal(SIGPIPE, SIG_IGN); /* generate I/O errors instead of signal 13 */ - moonbr_io_signalfd_read = -1; - moonbr_io_signalfd_write = -1; + { + int i; + for (i=0; i<=MOONBR_IO_MAXSIGNUM; i++) { + moonbr_io_signalfd_read(i) = -1; + moonbr_io_signalfd_write(i) = -1; + } + } lua_newtable(L); // module diff -r 4f965eda4c2f -r d4c82c90d244 reference.txt --- a/reference.txt Tue Jun 06 18:00:30 2017 +0200 +++ b/reference.txt Tue Jun 06 20:01:29 2017 +0200 @@ -396,16 +396,18 @@ number (e.g. 9 or 15, respectively). -### moonbridge_io.signalsocket(signal1, signal2, ...) +### moonbridge_io.signalsocket(signal) + +This function installs a signal handler. As argument, either the signal number +is passed (e.g. 15) or a name (e.g. "TERM"). -This function installs a signal handler for the signals with the numbers passed -as arguments and returns a socket which receives a byte for each received -signal. Optionally, a string may be used instead of the signal number (e.g. -"KILL" instead of 9, or "TERM" instead of 15). +The function returns a new socket object that receives a character (".") each +time a signal is received. -Subsequent calls of this function can extend the set of signals but will always -return the same socket. If the socket is closed, it is no longer possible to -detect signals until the process is terminated. +Note that each socket object has an independent buffer. It is thus recommended +to always read all bytes, e.g. by using the expression: + +#(assert(sigsock:read_nb())) > 0 -- true if signal occurred ### moonbridge_io.tcpconnect(hostname, port)