moonbridge
changeset 266:48ffca6443d9
Added moonbridge_io.signalsocket(...) and moonbridge_io.getpid() functions; poll returns true on signal interruption (instead of nil)
author | jbe |
---|---|
date | Sun Jun 04 16:40:46 2017 +0200 (2017-06-04) |
parents | 37aaca00941c |
children | 5f437005e2ef |
files | moonbridge_io.c reference.txt |
line diff
1.1 --- a/moonbridge_io.c Sun Jun 04 13:49:12 2017 +0200 1.2 +++ b/moonbridge_io.c Sun Jun 04 16:40:46 2017 +0200 1.3 @@ -55,11 +55,16 @@ 1.4 moonbr_io_return_prepared_errmsg(); \ 1.5 } while (0) 1.6 1.7 +static int moonbr_io_signalfds[2]; 1.8 +#define moonbr_io_signalfd_read moonbr_io_signalfds[0] 1.9 +#define moonbr_io_signalfd_write moonbr_io_signalfds[1] 1.10 + 1.11 #define MOONBR_IO_HANDLE_MT_REGKEY "moonbridge_io_handle" 1.12 #define MOONBR_IO_HANDLE_PUBLIC_MT_REGKEY "moonbridge_io_handle_public" 1.13 #define MOONBR_IO_LISTENER_MT_REGKEY "moonbridge_io_listener" 1.14 #define MOONBR_IO_CHILD_MT_REGKEY "moonbridge_io_child" 1.15 #define MOONBR_IO_CHILD_PT_REGKEY "moonbridge_io_child_pt" 1.16 +#define MOONBR_IO_SIGNALSOCKET_REGKEY "moonbridge_io_signalsocket" 1.17 1.18 #ifdef MOONBR_IO_USE_TLS 1.19 1.20 @@ -1607,6 +1612,44 @@ 1.21 1.22 moonbr_io_yield_wrapper(moonbr_io_wait_yield, moonbr_io_wait_call); 1.23 1.24 +static void moonbr_io_signalhandler(int sig) { 1.25 + int errno2 = errno; 1.26 + char buf[1] = {sig}; 1.27 + write(moonbr_io_signalfd_write, buf, 1); 1.28 + errno = errno2; 1.29 +} 1.30 + 1.31 +static int moonbr_io_signalsocket(lua_State *L) { 1.32 + int i, argc, sig; 1.33 + if (moonbr_io_signalfd_read < 0) { 1.34 + if (socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, moonbr_io_signalfds)) { 1.35 + luaL_error(L, "Could not create socket pair for signal queueing"); 1.36 + } 1.37 + } 1.38 + argc = lua_gettop(L); 1.39 + for (i=1; i<=argc; i++) { 1.40 + sig = luaL_checkinteger(L, i); 1.41 + errno = 0; 1.42 + signal(sig, moonbr_io_signalhandler); 1.43 + if (errno) luaL_error(L, "Could not install signal handler (invalid signal number?)"); 1.44 + } 1.45 + lua_settop(L, 0); 1.46 + lua_getfield(L, LUA_REGISTRYINDEX, MOONBR_IO_SIGNALSOCKET_REGKEY); 1.47 + if (lua_isnil(L, -1)) { 1.48 + int fd = dup(moonbr_io_signalfd_read); /* TODO: determine how mooonbr_io_pushhandle acts in case of error */ 1.49 + if (fd < 0) luaL_error(L, "Error in dup() system call"); 1.50 + moonbr_io_pushhandle(L, fd); 1.51 + lua_pushvalue(L, -1); 1.52 + lua_setfield(L, LUA_REGISTRYINDEX, MOONBR_IO_SIGNALSOCKET_REGKEY); 1.53 + } 1.54 + return 1; 1.55 +} 1.56 + 1.57 +static int moonbr_io_getpid(lua_State *L) { 1.58 + lua_pushinteger(L, getpid()); 1.59 + return 1; 1.60 +} 1.61 + 1.62 #ifdef MOONBR_IO_USE_TLS 1.63 1.64 #define moonbr_io_poll_tls() \ 1.65 @@ -1724,9 +1767,8 @@ 1.66 } 1.67 if (status == -1) { 1.68 if (errno == EINTR) { 1.69 - lua_pushnil(L); 1.70 - lua_pushliteral(L, "Signal received while polling file descriptors"); 1.71 - return 2; 1.72 + lua_pushboolean(L, 1); 1.73 + return 1; 1.74 } else { 1.75 moonbr_io_prepare_errmsg(); 1.76 return luaL_error(L, "Unexpected error during \"select\" system call: %s", errmsg); 1.77 @@ -1957,6 +1999,8 @@ 1.78 {"locallisten", moonbr_io_locallisten}, 1.79 {"tcplisten", moonbr_io_tcplisten}, 1.80 {"exec", moonbr_io_exec}, 1.81 + {"signalsocket", moonbr_io_signalsocket}, 1.82 + {"getpid", moonbr_io_getpid}, 1.83 {"poll", moonbr_io_poll}, 1.84 {"timeref", moonbr_io_timeref}, 1.85 #ifdef MOONBR_IO_USE_TLS 1.86 @@ -1977,6 +2021,8 @@ 1.87 int luaopen_moonbridge_io(lua_State *L) { 1.88 1.89 signal(SIGPIPE, SIG_IGN); /* generate I/O errors instead of signal 13 */ 1.90 + moonbr_io_signalfd_read = -1; 1.91 + moonbr_io_signalfd_write = -1; 1.92 1.93 lua_newtable(L); // module 1.94
2.1 --- a/reference.txt Sun Jun 04 13:49:12 2017 +0200 2.2 +++ b/reference.txt Sun Jun 04 16:40:46 2017 +0200 2.3 @@ -386,9 +386,19 @@ 2.4 nil, it is treated as being empty. 2.5 2.6 Returns true when at least one file descriptor or handle is ready for reading 2.7 -or writing respectively. Returns false (plus a notice as second return value) 2.8 -in case of timeout. Returns nil (plus a notice as second return value) if a 2.9 -signal was received during waiting. 2.10 +or writing respectively, or if a signal has been received during waiting. 2.11 +Returns false (plus a notice as second return value) in case of timeout. 2.12 + 2.13 + 2.14 +### moonbridge_io.signalsocket(signal, ...) 2.15 + 2.16 +This function installs a signal handler for the signals with the numbers passed 2.17 +as arguments and returns a socket which receives a byte for each received 2.18 +signal. 2.19 + 2.20 +Subsequent calls of this function can extend the set of signals but will always 2.21 +return the same socket. If the socket is closed, it is no longer possible to 2.22 +detect signals until the process is terminated. 2.23 2.24 2.25 ### moonbridge_io.tcpconnect(hostname, port)