# HG changeset patch # User jbe # Date 1428448323 -7200 # Node ID 719f83c7fea412b405b84ab81750f308b851bb2c # Parent de3982f17d05c971dca42f2a2f3bdcf5fe3be6be Correctly cache nonblocking status of socket in I/O library; Use TCP_NOPUSH/TCP_CORK when applicable diff -r de3982f17d05 -r 719f83c7fea4 moonbridge_io.c --- a/moonbridge_io.c Tue Apr 07 22:17:13 2015 +0200 +++ b/moonbridge_io.c Wed Apr 08 01:12:03 2015 +0200 @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -25,10 +27,11 @@ typedef struct { int fd; - int useshutdown; + int isnetwork; int finished; int closed; int nonblocking; + int nopush; int readerr; int readbufcnt; int writeerr; @@ -47,35 +50,55 @@ } moonbr_io_handle_t; static void moonbr_io_handle_set_nonblocking(lua_State *L, moonbr_io_handle_t *handle, int nonblocking) { - if (handle->nonblocking != nonblocking) { - int flags; - flags = fcntl(handle->fd, F_GETFL, 0); - if (flags == -1) { - moonbr_io_errmsg(); - luaL_error(L, "Unexpected error in fcntl call: %s", errmsg); - } - if (nonblocking) flags |= O_NONBLOCK; - else flags &= ~O_NONBLOCK; - if (fcntl(handle->fd, F_SETFL, flags) == -1) { - moonbr_io_errmsg(); - luaL_error(L, "Unexpected error in fcntl call: %s", errmsg); - } + int flags; + if (handle->nonblocking == nonblocking) return; + flags = fcntl(handle->fd, F_GETFL, 0); + if (flags == -1) { + moonbr_io_errmsg(); + handle->nonblocking = -1; + luaL_error(L, "Unexpected error in fcntl call: %s", errmsg); } + if (nonblocking) flags |= O_NONBLOCK; + else flags &= ~O_NONBLOCK; + if (fcntl(handle->fd, F_SETFL, flags) == -1) { + moonbr_io_errmsg(); + handle->nonblocking = -1; + luaL_error(L, "Unexpected error in fcntl call: %s", errmsg); + } + handle->nonblocking = nonblocking; } static void moonbr_io_handle_set_linger(lua_State *L, moonbr_io_handle_t *handle, int timeout) { struct linger lingerval = { 0, }; - if (!handle->useshutdown) return; + if (!handle->isnetwork) 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); + luaL_error(L, "Unexpected error while setting SO_LINGER with setsockopt: %s", errmsg); } } +static void moonbr_io_handle_set_nopush(lua_State *L, moonbr_io_handle_t *handle, int nopush) { + if (!handle->isnetwork || handle->nopush == nopush) return; +#if defined(TCP_CORK) && !defined(TCP_NOPUSH) + if (setsockopt(handle->fd, IPPROTO_TCP, TCP_CORK, &nopush, sizeof(nopush))) { + moonbr_io_errmsg(); + handle->nopush = -1; + luaL_error(L, "Unexpected error while setting TCP_CORK with setsockopt: %s", errmsg); + } +#else + if (setsockopt(handle->fd, IPPROTO_TCP, TCP_NOPUSH, &nopush, sizeof(nopush))) { + moonbr_io_errmsg(); + handle->nopush = -1; + luaL_error(L, "Unexpected error while setting TCP_NOPUSH with setsockopt: %s", errmsg); + } +#endif + handle->nopush = nopush; +} + static int moonbr_io_read_impl(lua_State *L, int nonblocking, int drain) { moonbr_io_handle_t *handle; lua_Integer maxread; @@ -210,6 +233,10 @@ handle->writebufcnt += strlen - handle->writeqoff; break; } else { + moonbr_io_handle_set_nopush(L, handle, + (flush || handle->writeleft == MOONBR_IO_WRITEBUFLEN) ? + 0 : 1 + ); written = 0; memcpy(handle->writebuf + handle->writebufcnt, str + handle->writeqoff, MOONBR_IO_WRITEBUFLEN - handle->writebufcnt); handle->writeqoff += MOONBR_IO_WRITEBUFLEN - handle->writebufcnt; @@ -309,7 +336,7 @@ } } handle->finished = 1; - if (handle->useshutdown) { + if (handle->isnetwork) { if (shutdown(handle->fd, SHUT_WR)) { moonbr_io_errmsg(); lua_pushnil(L); @@ -393,14 +420,15 @@ } } -void moonbr_io_pushhandle(lua_State *L, int fd, int useshutdown) { +void moonbr_io_pushhandle(lua_State *L, int fd, int isnetwork) { moonbr_io_handle_t *handle; handle = lua_newuserdata(L, sizeof(moonbr_io_handle_t)); handle->fd = fd; - handle->useshutdown = useshutdown; + handle->isnetwork = isnetwork; handle->finished = 0; handle->closed = 0; handle->nonblocking = -1; + handle->nopush = -1; handle->readerr = 0; handle->readbufcnt = 0; handle->writeerr = 0;