moonbridge
diff moonbridge.c @ 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 | 460e457730a2 |
children | d4265136ce88 |
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 */