# HG changeset patch # User jbe # Date 1428362275 -7200 # Node ID 1d91c6eedf18429970b1b324107998e60af67fe8 # Parent 9fa3a36733ff7e9a48c4e4877824dce873e69f03 Close and reset method for I/O library diff -r 9fa3a36733ff -r 1d91c6eedf18 moonbridge_io.c --- a/moonbridge_io.c Tue Apr 07 00:47:30 2015 +0200 +++ b/moonbridge_io.c Tue Apr 07 01:17:55 2015 +0200 @@ -61,6 +61,19 @@ } } +static void moonbr_io_handle_set_linger(lua_State *L, moonbr_io_handle_t *handle, int timeout) { + struct linger lingerval = { 0, }; + if (!handle->issocket) return; + 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(); + luaL_error(L, "Unexpected error in setsockopt call: %s", errmsg); + } +} + static int moonbr_io_read_impl(lua_State *L, int nonblocking, int drain) { moonbr_io_handle_t *handle; lua_Integer maxread; @@ -264,19 +277,24 @@ return moonbr_io_write_impl(L, 1, 1); } -static int moonbr_io_close_impl(lua_State *L, int clean) { +static int moonbr_io_close(lua_State *L) { moonbr_io_handle_t *handle; + int timeout; handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); + timeout = luaL_optinteger(L, 2, -1); if (handle->fd < 0) luaL_error(L, "Attempt to close a closed I/O handle"); - if (clean && handle->writeleft) { - lua_pushcfunction(L, moonbr_io_flush); - lua_pushvalue(L, 1); - lua_call(L, 1, 2); - if (!lua_toboolean(L, -2)) { - close(handle->fd); - handle->fd = -1; - return 2; + if (timeout != 0) { + if (handle->writeleft) { + lua_pushcfunction(L, moonbr_io_flush); + lua_pushvalue(L, 1); + lua_call(L, 1, 2); + if (!lua_toboolean(L, -2)) { + close(handle->fd); + handle->fd = -1; + return 2; + } } + moonbr_io_handle_set_linger(L, handle, timeout); } if (close(handle->fd)) { moonbr_io_errmsg(); @@ -292,11 +310,13 @@ } static int moonbr_io_reset(lua_State *L) { - return moonbr_io_close_impl(L, 0); -} - -static int moonbr_io_close(lua_State *L) { - return moonbr_io_close_impl(L, 1); + luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); + lua_settop(L, 1); + lua_pushcfunction(L, moonbr_io_close); + lua_insert(L, 1); + lua_pushinteger(L, 0); + lua_call(L, 2, LUA_MULTRET); + return lua_gettop(L); } void moonbr_io_pushhandle(lua_State *L, int fd, int issocket) { @@ -313,6 +333,7 @@ handle->writeqout = 0; handle->writeqoff = 0; handle->writebufcnt = 0; + moonbr_io_handle_set_linger(L, handle, 0); luaL_getmetatable(L, MOONBR_IO_HANDLE_MT_REGKEY); lua_setmetatable(L, -2); lua_newtable(L); // uservalue @@ -344,23 +365,6 @@ return 0; } -static int moonbr_io_handlegc(lua_State *L) { - moonbr_io_handle_t *handle; - handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); - if (handle->fd >= 0) { - lua_getuservalue(L, 1); - lua_getfield(L, -1, "gc"); - lua_pushvalue(L, 1); - lua_call(L, 1, 0); - } - return 0; -} - -static int moonbr_io_getdummy(lua_State *L) { - moonbr_io_pushhandle(L, 0, 0); - return 1; -} - static const struct luaL_Reg moonbr_io_handle_methods[] = { {"read", moonbr_io_read}, {"read_nb", moonbr_io_read_nb}, @@ -370,20 +374,19 @@ {"write_nb", moonbr_io_write_nb}, {"flush", moonbr_io_flush}, {"flush_nb", moonbr_io_flush_nb}, + {"close", moonbr_io_close}, {"reset", moonbr_io_reset}, - {"close", moonbr_io_close}, {NULL, NULL} }; static const struct luaL_Reg moonbr_io_handle_metamethods[] = { {"__index", moonbr_io_handleindex}, {"__newindex", moonbr_io_handlenewindex}, - {"__gc", moonbr_io_handlegc}, + {"__gc", moonbr_io_reset}, {NULL, NULL} }; static const struct luaL_Reg moonbr_io_module_funcs[] = { - {"getdummy", moonbr_io_getdummy}, {NULL, NULL} };