moonbridge

changeset 75:9fff0cb4fc65

Proper handling of out-of-memory errors in xread_nb method
author jbe
date Sat Apr 04 23:32:24 2015 +0200 (2015-04-04)
parents 88541c2aab4d
children d4265136ce88
files moonbridge.c
line diff
     1.1 --- a/moonbridge.c	Sat Apr 04 22:42:49 2015 +0200
     1.2 +++ b/moonbridge.c	Sat Apr 04 23:32:24 2015 +0200
     1.3 @@ -2305,6 +2305,7 @@
     1.4  #endif
     1.5        stream = luaL_testudata(L, -1, LUA_FILEHANDLE);
     1.6        if (stream) {
     1.7 +        /* in case of file handle, check for pending data in buffer */
     1.8          FILE *file = stream->f;
     1.9          int flags, chr;
    1.10          flockfile(file);
    1.11 @@ -2396,14 +2397,14 @@
    1.12    }
    1.13  }
    1.14  
    1.15 -/* New methods for Lua file objects: read until terminator or length exceeded (optional non-blocking) */
    1.16 +/* New methods for Lua file objects: read until terminator or length exceeded (blocking and non-blocking) */
    1.17  static int moonbr_io_xread_impl(lua_State *L, int nonblock) {
    1.18    luaL_Stream *stream;
    1.19    lua_Integer maxlen;
    1.20    const char *terminatorstr;
    1.21    size_t terminatorlen;
    1.22    FILE *file;
    1.23 -  int fd, flags, chr, terminator;
    1.24 +  int chr, terminator;
    1.25    luaL_Buffer buf;
    1.26    int wouldblock = 0;
    1.27    stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
    1.28 @@ -2417,15 +2418,6 @@
    1.29      lua_pushliteral(L, "Previous error condition on file handle");
    1.30      return 2;
    1.31    }
    1.32 -  if (nonblock) {
    1.33 -    fd = fileno(file);
    1.34 -    flags = fcntl(fd, F_GETFL, 0);
    1.35 -    if (flags == -1) goto moonbr_io_xread_impl_error;
    1.36 -    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_xread_impl_error;
    1.37 -  } else {
    1.38 -    fd = -1;  /* avoids compiler warning */
    1.39 -    flags = 0;  /* avoids compiler warning */
    1.40 -  }
    1.41    if (!maxlen) maxlen = -1;
    1.42    terminator = terminatorlen ? terminatorstr[0] : -1;
    1.43    luaL_buffinit(L, &buf);
    1.44 @@ -2439,7 +2431,6 @@
    1.45          } else {
    1.46            char errmsg[MOONBR_MAXSTRERRORLEN];
    1.47            strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
    1.48 -          if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_impl_error;
    1.49            lua_pushnil(L);
    1.50            lua_pushstring(L, errmsg);
    1.51            return 2;
    1.52 @@ -2450,9 +2441,6 @@
    1.53      luaL_addchar(&buf, chr);
    1.54      if (chr == terminator) break;
    1.55    }
    1.56 -  if (nonblock) {
    1.57 -    if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_impl_error;
    1.58 -  }
    1.59    luaL_pushresult(&buf);
    1.60    if (wouldblock || lua_rawlen(L, -1)) {
    1.61      return 1;
    1.62 @@ -2461,18 +2449,37 @@
    1.63      lua_pushliteral(L, "End of file");
    1.64      return 2;
    1.65    }
    1.66 -  moonbr_io_xread_impl_error:
    1.67 -  {
    1.68 -    char errmsg[MOONBR_MAXSTRERRORLEN];
    1.69 -    strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
    1.70 -    return luaL_error(L, "Unexpected error in xread method: %s", errmsg);
    1.71 -  }
    1.72  }
    1.73  static int moonbr_io_xread(lua_State *L) {
    1.74    return moonbr_io_xread_impl(L, 0);
    1.75  }
    1.76 +static int moonbr_io_xread_nb_impl(lua_State *L) {
    1.77 +  return moonbr_io_xread_impl(L, 1);
    1.78 +}
    1.79  static int moonbr_io_xread_nb(lua_State *L) {
    1.80 -  return moonbr_io_xread_impl(L, 1);
    1.81 +  luaL_Stream *stream;
    1.82 +  int fd, flags;
    1.83 +  stream = luaL_checkudata(L, 1, LUA_FILEHANDLE);
    1.84 +  if (!stream->closef) luaL_error(L, "attempt to use a closed file");
    1.85 +  lua_pushcfunction(L, moonbr_io_xread_nb_impl);
    1.86 +  lua_insert(L, 1);
    1.87 +  lua_settop(L, 4);
    1.88 +  fd = fileno(stream->f);
    1.89 +  flags = fcntl(fd, F_GETFL, 0);
    1.90 +  if (flags == -1) goto moonbr_io_xread_nb_error;
    1.91 +  if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_xread_nb_error;
    1.92 +  if (lua_pcall(L, 3, LUA_MULTRET, 0)) {
    1.93 +    fcntl(fd, F_SETFL, flags);
    1.94 +    return lua_error(L);
    1.95 +  }
    1.96 +  if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_nb_error;
    1.97 +  return lua_gettop(L);
    1.98 +  moonbr_io_xread_nb_error:
    1.99 +  {
   1.100 +    char errmsg[MOONBR_MAXSTRERRORLEN];
   1.101 +    strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN);  /* use thread-safe call in case child created threads */
   1.102 +    return luaL_error(L, "Unexpected error in xread_nb method: %s", errmsg);
   1.103 +  }
   1.104  }
   1.105  
   1.106  /* New methods for Lua file objects: non-blocking writing */

Impressum / About Us