# HG changeset patch # User jbe # Date 1496587246 -7200 # Node ID 48ffca6443d99b774f9f27573926fbb0ff572020 # Parent 37aaca00941cd944ee4615def4bc41835eab2cc1 Added moonbridge_io.signalsocket(...) and moonbridge_io.getpid() functions; poll returns true on signal interruption (instead of nil) diff -r 37aaca00941c -r 48ffca6443d9 moonbridge_io.c --- a/moonbridge_io.c Sun Jun 04 13:49:12 2017 +0200 +++ b/moonbridge_io.c Sun Jun 04 16:40:46 2017 +0200 @@ -55,11 +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_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" #ifdef MOONBR_IO_USE_TLS @@ -1607,6 +1612,44 @@ moonbr_io_yield_wrapper(moonbr_io_wait_yield, moonbr_io_wait_call); +static void moonbr_io_signalhandler(int sig) { + int errno2 = errno; + char buf[1] = {sig}; + write(moonbr_io_signalfd_write, 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"); + } + } + argc = lua_gettop(L); + for (i=1; i<=argc; i++) { + sig = luaL_checkinteger(L, i); + errno = 0; + signal(sig, moonbr_io_signalhandler); + if (errno) luaL_error(L, "Could not install signal handler (invalid signal number?)"); + } + 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); + } + return 1; +} + +static int moonbr_io_getpid(lua_State *L) { + lua_pushinteger(L, getpid()); + return 1; +} + #ifdef MOONBR_IO_USE_TLS #define moonbr_io_poll_tls() \ @@ -1724,9 +1767,8 @@ } if (status == -1) { if (errno == EINTR) { - lua_pushnil(L); - lua_pushliteral(L, "Signal received while polling file descriptors"); - return 2; + lua_pushboolean(L, 1); + return 1; } else { moonbr_io_prepare_errmsg(); return luaL_error(L, "Unexpected error during \"select\" system call: %s", errmsg); @@ -1957,6 +1999,8 @@ {"locallisten", moonbr_io_locallisten}, {"tcplisten", moonbr_io_tcplisten}, {"exec", moonbr_io_exec}, + {"signalsocket", moonbr_io_signalsocket}, + {"getpid", moonbr_io_getpid}, {"poll", moonbr_io_poll}, {"timeref", moonbr_io_timeref}, #ifdef MOONBR_IO_USE_TLS @@ -1977,6 +2021,8 @@ 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; lua_newtable(L); // module diff -r 37aaca00941c -r 48ffca6443d9 reference.txt --- a/reference.txt Sun Jun 04 13:49:12 2017 +0200 +++ b/reference.txt Sun Jun 04 16:40:46 2017 +0200 @@ -386,9 +386,19 @@ nil, it is treated as being empty. Returns true when at least one file descriptor or handle is ready for reading -or writing respectively. Returns false (plus a notice as second return value) -in case of timeout. Returns nil (plus a notice as second return value) if a -signal was received during waiting. +or writing respectively, or if a signal has been received during waiting. +Returns false (plus a notice as second return value) in case of timeout. + + +### moonbridge_io.signalsocket(signal, ...) + +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. + +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. ### moonbridge_io.tcpconnect(hostname, port)