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 -Returns true when at least one file descriptor or handle is ready for reading
    5.32 -or writing respectively. The function may also return true if signals have been
    5.33 -received during waiting (unless the 4th parameter is set to true and a SIGTERM
    5.34 -was received).
    5.35 +The function returns true when at least one file descriptor or handle is ready
    5.36 +for reading or writing respectively. The function may also return true (for
    5.37 +technical reasons) if signals other than SIGTERM have been received during
    5.38 +waiting.
    5.39 +
    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

Impressum / About Us