moonbridge
changeset 288:524bb61496b5
Changed behavior of moonbridge_io.poll(...); Renamed moonbridge_io.sigterm_setup() to moonbridge_io.catch_sigterm(); Removed moonbridge_io.sigterm_received()
author | jbe |
---|---|
date | Sun Jun 11 03:50:28 2017 +0200 (2017-06-11) |
parents | 2fe69234cbe9 |
children | 76bede490cdf |
files | moonbridge.c moonbridge_http.lua moonbridge_io.c moonbridge_io.h reference.txt |
line diff
1.1 --- a/moonbridge.c Sun Jun 11 01:27:52 2017 +0200 1.2 +++ b/moonbridge.c Sun Jun 11 03:50:28 2017 +0200 1.3 @@ -755,7 +755,7 @@ 1.4 char controlmsg; 1.5 int fd; 1.6 struct itimerval notimer = { { 0, }, { 0, } }; 1.7 - moonbr_io_sigterm_setup(L); // NOTE: should not fail 1.8 + moonbr_io_catch_sigterm(L); // NOTE: should not fail 1.9 lua_rawgetp(L, LUA_REGISTRYINDEX, moonbr_luakey_prepare_func(pool)); 1.10 if (lua_isnil(L, -1)) lua_pop(L, 1); 1.11 else if (lua_pcall(L, 0, 0, 1)) {
2.1 --- a/moonbridge_http.lua Sun Jun 11 01:27:52 2017 +0200 2.2 +++ b/moonbridge_http.lua Sun Jun 11 03:50:28 2017 +0200 2.3 @@ -1094,11 +1094,13 @@ 2.4 return true -- success 2.5 end 2.6 -- wait for input: 2.7 - if not poll(socket_set, nil, idle_timeout, true) then 2.8 - if moonbridge_io.sigterm_received() then 2.9 + local ready, pollmsg, quit = poll(socket_set, nil, idle_timeout, true) 2.10 + if not ready then 2.11 + if quit then 2.12 return request_error(false, "408 Request Timeout", "Server shutdown") 2.13 + else 2.14 + return request_error(false, "408 Request Timeout", "Idle connection timed out") 2.15 end 2.16 - return request_error(false, "408 Request Timeout", "Idle connection timed out") 2.17 end 2.18 -- read headers (with timeout): 2.19 do
3.1 --- a/moonbridge_io.c Sun Jun 11 01:27:52 2017 +0200 3.2 +++ b/moonbridge_io.c Sun Jun 11 03:50:28 2017 +0200 3.3 @@ -1615,16 +1615,11 @@ 3.4 moonbr_io_sigterm_flag = 1; 3.5 } 3.6 3.7 -int moonbr_io_sigterm_setup(lua_State *L) { 3.8 +int moonbr_io_catch_sigterm(lua_State *L) { 3.9 signal(SIGTERM, moonbr_io_sigterm_handler); 3.10 return 0; 3.11 } 3.12 3.13 -static int moonbr_io_sigterm_received(lua_State *L) { 3.14 - lua_pushboolean(L, moonbr_io_sigterm_flag); 3.15 - return 1; 3.16 -} 3.17 - 3.18 static int moonbr_io_getpid(lua_State *L) { 3.19 lua_pushinteger(L, getpid()); 3.20 return 1; 3.21 @@ -1666,7 +1661,7 @@ 3.22 int nfds = 0; 3.23 fd_set readfds, writefds, exceptfds; 3.24 struct timespec timeout = {0, }; 3.25 - int use_timeout = 0; 3.26 + int use_timeout = 0; // negative for negative timeout 3.27 int check_sigterm = 0; 3.28 sigset_t mask, orig_mask; 3.29 int status; 3.30 @@ -1735,36 +1730,50 @@ 3.31 lua_Number n; 3.32 n = lua_tonumberx(L, 3, &isnum); 3.33 if (isnum && n<0) { 3.34 - lua_pushboolean(L, 0); 3.35 - lua_pushliteral(L, "Negative timeout"); 3.36 - return 2; 3.37 + use_timeout = -1; 3.38 } else if (isnum && n>=0 && n<100000000) { 3.39 + use_timeout = 1; 3.40 timeout.tv_sec = n; 3.41 timeout.tv_nsec = 1e9 * (n - timeout.tv_sec); 3.42 } else { 3.43 luaL_argcheck(L, 0, 3, "not a valid timeout"); 3.44 } 3.45 - use_timeout = 1; 3.46 } 3.47 if (!lua_isnoneornil(L, 4)) luaL_checktype(L, 4, LUA_TBOOLEAN); 3.48 check_sigterm = lua_toboolean(L, 4); 3.49 if (check_sigterm) { 3.50 sigemptyset(&mask); 3.51 sigaddset(&mask, SIGTERM); 3.52 - sigprocmask(SIG_BLOCK, &mask, &orig_mask); 3.53 + if (use_timeout >= 0) sigprocmask(SIG_BLOCK, &mask, &orig_mask); 3.54 if (moonbr_io_sigterm_flag) { 3.55 - if (sigprocmask(SIG_SETMASK, &orig_mask, NULL)) abort(); 3.56 + if (use_timeout >= 0) if (sigprocmask(SIG_SETMASK, &orig_mask, NULL)) abort(); 3.57 lua_pushboolean(L, 0); 3.58 lua_pushliteral(L, "SIGTERM received"); 3.59 + lua_pushboolean(L, 1); 3.60 + return 3; 3.61 + } 3.62 + } 3.63 + if (use_timeout < 0) { 3.64 + lua_pushboolean(L, 0); 3.65 + lua_pushliteral(L, "Negative timeout"); 3.66 + if (check_sigterm) { 3.67 + lua_pushboolean(L, 0); 3.68 + return 3; 3.69 + } else { 3.70 return 2; 3.71 } 3.72 } 3.73 - status = pselect(nfds, &readfds, &writefds, &exceptfds, use_timeout ? &timeout : NULL, check_sigterm ? &orig_mask : NULL); 3.74 + status = pselect( 3.75 + nfds, &readfds, &writefds, &exceptfds, 3.76 + use_timeout ? &timeout : NULL, 3.77 + check_sigterm ? &orig_mask : NULL 3.78 + ); 3.79 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL)) abort(); 3.80 - if (moonbr_io_sigterm_flag) { 3.81 + if (check_sigterm && moonbr_io_sigterm_flag) { 3.82 lua_pushboolean(L, 0); 3.83 lua_pushliteral(L, "SIGTERM received"); 3.84 - return 2; 3.85 + lua_pushboolean(L, 1); 3.86 + return 3; 3.87 } 3.88 if (status == -1) { 3.89 if (errno == EINTR) { 3.90 @@ -1776,8 +1785,13 @@ 3.91 } 3.92 } else if (status == 0) { 3.93 lua_pushboolean(L, 0); 3.94 - lua_pushliteral(L, "Timeout while polling file descriptors"); 3.95 - return 2; 3.96 + lua_pushliteral(L, "Timeout while waiting for I/O"); 3.97 + if (check_sigterm) { 3.98 + lua_pushboolean(L, 0); 3.99 + return 3; 3.100 + } else { 3.101 + return 2; 3.102 + } 3.103 } else { 3.104 lua_pushboolean(L, 1); 3.105 return 1; 3.106 @@ -2000,8 +2014,7 @@ 3.107 {"locallisten", moonbr_io_locallisten}, 3.108 {"tcplisten", moonbr_io_tcplisten}, 3.109 {"exec", moonbr_io_exec}, 3.110 - {"sigterm_setup", moonbr_io_sigterm_setup}, 3.111 - {"sigterm_received", moonbr_io_sigterm_received}, 3.112 + {"catch_sigterm", moonbr_io_catch_sigterm}, 3.113 {"getpid", moonbr_io_getpid}, 3.114 {"poll", moonbr_io_poll}, 3.115 {"timeref", moonbr_io_timeref},
4.1 --- a/moonbridge_io.h Sun Jun 11 01:27:52 2017 +0200 4.2 +++ b/moonbridge_io.h Sun Jun 11 03:50:28 2017 +0200 4.3 @@ -1,6 +1,6 @@ 4.4 4.5 void moonbr_io_pushhandle(lua_State *L, int fd); 4.6 void moonbr_io_closehandle(lua_State *L, int idx, int reset); 4.7 -int moonbr_io_sigterm_setup(lua_State *L); 4.8 +int moonbr_io_catch_sigterm(lua_State *L); 4.9 int luaopen_moonbridge_io(lua_State *L); 4.10
5.1 --- a/reference.txt Sun Jun 11 01:27:52 2017 +0200 5.2 +++ b/reference.txt Sun Jun 11 03:50:28 2017 +0200 5.3 @@ -299,6 +299,15 @@ 5.4 listed below. 5.5 5.6 5.7 +### moonbridge_io.catch_sigterm() 5.8 + 5.9 +This function installs a signal handler for SIGTERM. Instead of causing 5.10 +immediate process termination, the behavior of moonbridge_io.poll(...) is 5.11 +modified. 5.12 + 5.13 +See moonbridge_io.poll(...) for further information. 5.14 + 5.15 + 5.16 ### moonbridge_io.exec(command, arg1, arg2, ...) 5.17 5.18 Executes the given command and returns a handle with three sockets named 5.19 @@ -390,35 +399,34 @@ 5.20 which does evaluate to true, e.g. input_set = {[socketA] = true}. If a set is 5.21 nil, it is treated as being empty. 5.22 5.23 -Returns false (plus a notice as second return value) in case of timeout. If the 5.24 -4th parameter is set to true, also returns false (plus a notice) when a SIGTERM 5.25 -has been received since a corresponding signal handler has been installed with 5.26 -moonbridge_io.sigterm_setup(). 5.27 +If the 4th parameter (wakeup_on_sigterm) is set to true, then the function 5.28 +returns immediately if the process received at least one SIGTERM signal after 5.29 +moonbridge_io.catch_sigterm() has been called for the first time. 5.30 + 5.31 +The function returns true when at least one file descriptor or handle is ready 5.32 +for reading or writing respectively. The function may also return true (for 5.33 +technical reasons) if signals other than SIGTERM have been received during 5.34 +waiting. 5.35 5.36 -Returns true when at least one file descriptor or handle is ready for reading 5.37 -or writing respectively. The function may also return true if signals have been 5.38 -received during waiting (unless the 4th parameter is set to true and a SIGTERM 5.39 -was received). 5.40 +If the 4th parameter (wakeup_on_sigterm) is omitted or set to false, then the 5.41 +function only returns false as first return value if a timeout happened. In 5.42 +this case, the second return value will be set to an appropriate message string 5.43 +such that assert(moonbridge_io.poll(...)) can be used to throw an error. 5.44 + 5.45 +If the 4th parameter (wakeup_on_sigterm) is set to true, then three values are 5.46 +returned if a timeout happened or a SIGTERM has been received: false as first 5.47 +return value, a message string as second return value (that may, for example, 5.48 +be used for assert(...)), and a boolean as third return value which indicates 5.49 +whether the function prematurely returned because of SIGTERM. 5.50 + 5.51 +this case a corresponding message will be provided as second return value such 5.52 +that it is possible to call assert(moonbride_io.poll(...)) to raise an error if 5.53 +a timeout occurs. 5.54 5.55 Note that the function is not thread-safe when the 4th parameter is set to 5.56 true. 5.57 5.58 5.59 -### moonbridge_io.sigterm_received() 5.60 - 5.61 -Returns true if a SIGTERM was received after moonbridge_io.sigterm_setup() has 5.62 -installed a corresponding signal handler. The function will then always return 5.63 -true until the process terminates. 5.64 - 5.65 - 5.66 -### moonbridge_io.sigterm_setup() 5.67 - 5.68 -This function installs a signal handler for SIGTERM. Use the function 5.69 -moonbridge_io.sigterm_received() to check whether the signal has been received. 5.70 -In addition, moonbridge_io.poll(...) will wakeup prematurely if the 5.71 -4th parameter is set to true. 5.72 - 5.73 - 5.74 ### moonbridge_io.tcpconnect(hostname, port) 5.75 5.76 Tries to open a TCP connection with the given host and TCP port number. Returns