# HG changeset patch # User jbe # Date 1428183144 -7200 # Node ID 9fff0cb4fc65dee29de3f69e31a06e701c182b00 # Parent 88541c2aab4d9375106fbbf929fad124f2ecec5c Proper handling of out-of-memory errors in xread_nb method diff -r 88541c2aab4d -r 9fff0cb4fc65 moonbridge.c --- a/moonbridge.c Sat Apr 04 22:42:49 2015 +0200 +++ b/moonbridge.c Sat Apr 04 23:32:24 2015 +0200 @@ -2305,6 +2305,7 @@ #endif stream = luaL_testudata(L, -1, LUA_FILEHANDLE); if (stream) { + /* in case of file handle, check for pending data in buffer */ FILE *file = stream->f; int flags, chr; flockfile(file); @@ -2396,14 +2397,14 @@ } } -/* New methods for Lua file objects: read until terminator or length exceeded (optional non-blocking) */ +/* New methods for Lua file objects: read until terminator or length exceeded (blocking and non-blocking) */ static int moonbr_io_xread_impl(lua_State *L, int nonblock) { luaL_Stream *stream; lua_Integer maxlen; const char *terminatorstr; size_t terminatorlen; FILE *file; - int fd, flags, chr, terminator; + int chr, terminator; luaL_Buffer buf; int wouldblock = 0; stream = luaL_checkudata(L, 1, LUA_FILEHANDLE); @@ -2417,15 +2418,6 @@ lua_pushliteral(L, "Previous error condition on file handle"); return 2; } - if (nonblock) { - fd = fileno(file); - flags = fcntl(fd, F_GETFL, 0); - if (flags == -1) goto moonbr_io_xread_impl_error; - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_xread_impl_error; - } else { - fd = -1; /* avoids compiler warning */ - flags = 0; /* avoids compiler warning */ - } if (!maxlen) maxlen = -1; terminator = terminatorlen ? terminatorstr[0] : -1; luaL_buffinit(L, &buf); @@ -2439,7 +2431,6 @@ } else { char errmsg[MOONBR_MAXSTRERRORLEN]; strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ - if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_impl_error; lua_pushnil(L); lua_pushstring(L, errmsg); return 2; @@ -2450,9 +2441,6 @@ luaL_addchar(&buf, chr); if (chr == terminator) break; } - if (nonblock) { - if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_impl_error; - } luaL_pushresult(&buf); if (wouldblock || lua_rawlen(L, -1)) { return 1; @@ -2461,18 +2449,37 @@ lua_pushliteral(L, "End of file"); return 2; } - moonbr_io_xread_impl_error: - { - char errmsg[MOONBR_MAXSTRERRORLEN]; - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ - return luaL_error(L, "Unexpected error in xread method: %s", errmsg); - } } static int moonbr_io_xread(lua_State *L) { return moonbr_io_xread_impl(L, 0); } +static int moonbr_io_xread_nb_impl(lua_State *L) { + return moonbr_io_xread_impl(L, 1); +} static int moonbr_io_xread_nb(lua_State *L) { - return moonbr_io_xread_impl(L, 1); + luaL_Stream *stream; + int fd, flags; + stream = luaL_checkudata(L, 1, LUA_FILEHANDLE); + if (!stream->closef) luaL_error(L, "attempt to use a closed file"); + lua_pushcfunction(L, moonbr_io_xread_nb_impl); + lua_insert(L, 1); + lua_settop(L, 4); + fd = fileno(stream->f); + flags = fcntl(fd, F_GETFL, 0); + if (flags == -1) goto moonbr_io_xread_nb_error; + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) goto moonbr_io_xread_nb_error; + if (lua_pcall(L, 3, LUA_MULTRET, 0)) { + fcntl(fd, F_SETFL, flags); + return lua_error(L); + } + if (fcntl(fd, F_SETFL, flags) == -1) goto moonbr_io_xread_nb_error; + return lua_gettop(L); + moonbr_io_xread_nb_error: + { + char errmsg[MOONBR_MAXSTRERRORLEN]; + strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ + return luaL_error(L, "Unexpected error in xread_nb method: %s", errmsg); + } } /* New methods for Lua file objects: non-blocking writing */