# HG changeset patch # User jbe # Date 1474153171 -7200 # Node ID ff7eea59be93e496d3651a1ead6b9d56a71d0fca # Parent a22a6c19457fbb677bcb009e611be15ca084fe03 Bugfix: Do not throw (hard) Lua error in moonbr_io_handle_set_nonblocking, moonbr_io_handle_set_linger, and moonbr_io_handle_set_nopush (may cause Lua error on connection reset) diff -r a22a6c19457f -r ff7eea59be93 moonbridge_io.c --- a/moonbridge_io.c Sat Sep 17 22:08:35 2016 +0200 +++ b/moonbridge_io.c Sun Sep 18 00:59:31 2016 +0200 @@ -128,82 +128,45 @@ return lua_gettop(L); \ } -static void moonbr_io_handle_set_nonblocking(lua_State *L, moonbr_io_handle_t *handle, int nonblocking) { +static int moonbr_io_handle_set_nonblocking(lua_State *L, moonbr_io_handle_t *handle, int nonblocking) { int flags; - if (handle->nonblocking == nonblocking) return; + if (handle->nonblocking == nonblocking) return 0; flags = fcntl(handle->fd, F_GETFL, 0); - if (flags == -1) { - moonbr_io_errmsg(); -#ifdef MOONBR_IO_USE_TLS - if (handle->tls) tls_close(handle->tls); -#endif - close(handle->fd); - handle->fd = -1; - handle->closed = 1; - luaL_error(L, "Unexpected error in fcntl call: %s", errmsg); - } + if (flags == -1) return -1; if (nonblocking) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; - if (fcntl(handle->fd, F_SETFL, flags) == -1) { - moonbr_io_errmsg(); -#ifdef MOONBR_IO_USE_TLS - if (handle->tls) tls_close(handle->tls); -#endif - close(handle->fd); - handle->fd = -1; - handle->closed = 1; - luaL_error(L, "Unexpected error in fcntl call: %s", errmsg); - } + if (fcntl(handle->fd, F_SETFL, flags) == -1) return -1; handle->nonblocking = nonblocking; + return 0; } -static void moonbr_io_handle_set_linger(lua_State *L, moonbr_io_handle_t *handle, int timeout) { +static int moonbr_io_handle_set_linger(lua_State *L, moonbr_io_handle_t *handle, int timeout) { struct linger lingerval = { 0, }; - if (!handle->issock) return; + if (!handle->issock) return 0; if (timeout >= 0) { lingerval.l_onoff = 1; lingerval.l_linger = timeout; } - if (setsockopt(handle->fd, SOL_SOCKET, SO_LINGER, &lingerval, sizeof(lingerval))) { - moonbr_io_errmsg(); -#ifdef MOONBR_IO_USE_TLS - if (handle->tls) tls_close(handle->tls); -#endif - close(handle->fd); - handle->fd = -1; - handle->closed = 1; - luaL_error(L, "Unexpected error while setting SO_LINGER with setsockopt: %s", errmsg); - } + if (setsockopt(handle->fd, SOL_SOCKET, SO_LINGER, &lingerval, sizeof(lingerval))) return -1; + return 0; } -static inline void moonbr_io_handle_set_nopush(lua_State *L, moonbr_io_handle_t *handle, int nopush) { +static inline int moonbr_io_handle_set_nopush(lua_State *L, moonbr_io_handle_t *handle, int nopush) { #if defined(TCP_NOPUSH) || defined(TCP_CORK) if ( !(handle->addrfam == AF_INET6 || handle->addrfam == AF_INET) || handle->nopush == nopush - ) return; + ) return 0; #if defined(TCP_NOPUSH) - if (setsockopt(handle->fd, IPPROTO_TCP, TCP_NOPUSH, &nopush, sizeof(nopush))) { + if (setsockopt(handle->fd, IPPROTO_TCP, TCP_NOPUSH, &nopush, sizeof(nopush))) return -1; #elif defined(TCP_CORK) - if (setsockopt(handle->fd, IPPROTO_TCP, TCP_CORK, &nopush, sizeof(nopush))) { -#endif - moonbr_io_errmsg(); -#ifdef MOONBR_IO_USE_TLS - if (handle->tls) tls_close(handle->tls); + if (setsockopt(handle->fd, IPPROTO_TCP, TCP_CORK, &nopush, sizeof(nopush))) return -1; #endif - close(handle->fd); - handle->fd = -1; - handle->closed = 1; -#if defined(TCP_NOPUSH) - luaL_error(L, "Unexpected error while setting TCP_NOPUSH with setsockopt: %s", errmsg); -#elif defined(TCP_CORK) - luaL_error(L, "Unexpected error while setting TCP_CORK with setsockopt: %s", errmsg); -#endif - } handle->nopush = nopush; #else #warning Neither TCP_NOPUSH nor TCP_CORK is available #endif + return 0; } static int moonbr_io_read_impl(lua_State *L, int nonblocking, int drain) { @@ -239,7 +202,12 @@ return 2; } handle->readerr = 1; - moonbr_io_handle_set_nonblocking(L, handle, nonblocking); + if (moonbr_io_handle_set_nonblocking(L, handle, nonblocking)) { + moonbr_io_errmsg(); + lua_pushnil(L); + lua_pushstring(L, errmsg); + return 2; + } if (!drain) luaL_buffinit(L, &luabuf); while (1) { remaining = -1; @@ -540,7 +508,12 @@ return 2; } handle->writeerr = 1; - moonbr_io_handle_set_nonblocking(L, handle, nonblocking); + if (moonbr_io_handle_set_nonblocking(L, handle, nonblocking)) { + moonbr_io_errmsg(); + lua_pushnil(L); + lua_pushstring(L, errmsg); + return 2; + } top = lua_gettop(L); lua_getuservalue(L, 1); lua_getfield(L, -1, "writequeue"); @@ -575,7 +548,12 @@ handle->writeqoff += MOONBR_IO_WRITEBUFLEN - handle->writebufin; handle->writebufin = MOONBR_IO_WRITEBUFLEN; while (handle->writebufout < MOONBR_IO_WRITEBUFLEN) { - moonbr_io_handle_set_nopush(L, handle, 1); + if (moonbr_io_handle_set_nopush(L, handle, 1)) { + moonbr_io_errmsg(); + lua_pushnil(L); + lua_pushstring(L, errmsg); + return 2; + } #ifdef MOONBR_IO_USE_TLS moonbr_io_write_tls( handle->writebuf + handle->writebufout, @@ -602,7 +580,12 @@ if (handle->flushedleft) { if (written >= handle->flushedleft) { handle->flushedleft = 0; - moonbr_io_handle_set_nopush(L, handle, 0); + if (moonbr_io_handle_set_nopush(L, handle, 0)) { + moonbr_io_errmsg(); + lua_pushnil(L); + lua_pushstring(L, errmsg); + return 2; + } } else { handle->flushedleft -= written; } @@ -619,7 +602,12 @@ lua_rawseti(L, -2, handle->writeqout++); } while (handle->flushedleft) { - moonbr_io_handle_set_nopush(L, handle, 1); + if (moonbr_io_handle_set_nopush(L, handle, 1)) { + moonbr_io_errmsg(); + lua_pushnil(L); + lua_pushstring(L, errmsg); + return 2; + } #ifdef MOONBR_IO_USE_TLS moonbr_io_write_tls( handle->writebuf + handle->writebufout, @@ -646,7 +634,12 @@ if (handle->flushedleft) { if (written >= handle->flushedleft) { handle->flushedleft = 0; - moonbr_io_handle_set_nopush(L, handle, 0); + if (moonbr_io_handle_set_nopush(L, handle, 0)) { + moonbr_io_errmsg(); + lua_pushnil(L); + lua_pushstring(L, errmsg); + return 2; + } } else { handle->flushedleft -= written; } @@ -795,18 +788,12 @@ lua_pushvalue(L, 1); if (lua_pcall(L, 1, 2, 0)) { handle->closed = 1; -#ifdef MOONBR_IO_USE_TLS - if (handle->tls) tls_close(handle->tls); -#endif close(handle->fd); handle->fd = -1; lua_error(L); } handle->closed = 1; if (!lua_toboolean(L, -2)) { -#ifdef MOONBR_IO_USE_TLS - if (handle->tls) tls_close(handle->tls); -#endif close(handle->fd); handle->fd = -1; return 2; @@ -814,7 +801,14 @@ } else { handle->closed = 1; } - moonbr_io_handle_set_linger(L, handle, -1); + if (moonbr_io_handle_set_linger(L, handle, -1)) { + moonbr_io_errmsg(); + close(handle->fd); + handle->fd = -1; + lua_pushnil(L); + lua_pushstring(L, errmsg); + return 2; + } } else { handle->closed = 1; } @@ -916,7 +910,11 @@ handle->tlshandshake = 0; #endif handle->fd = *fd; /* required for set_linger call */ - moonbr_io_handle_set_linger(L, handle, 0); + if (moonbr_io_handle_set_linger(L, handle, 0)) { + moonbr_io_errmsg(); + handle->fd = -1; + luaL_error(L, "Unexpected error while setting SO_LINGER with setsockopt: %s", errmsg); + } handle->fd = -1; /* avoid closing incomplete handle */ luaL_setmetatable(L, MOONBR_IO_HANDLE_MT_REGKEY); lua_newtable(L); // uservalue