moonbridge
changeset 94:de3982f17d05
Removed timeout option from socket:close(); Simulate shutdown for local sockets (Unix Domain Sockets)
author | jbe |
---|---|
date | Tue Apr 07 22:17:13 2015 +0200 (2015-04-07) |
parents | de0e69673953 |
children | 719f83c7fea4 |
files | moonbridge.c moonbridge_io.c moonbridge_io.h reference.txt |
line diff
1.1 --- a/moonbridge.c Tue Apr 07 04:08:41 2015 +0200 1.2 +++ b/moonbridge.c Tue Apr 07 22:17:13 2015 +0200 1.3 @@ -842,7 +842,7 @@ 1.4 } 1.5 if (controlmsg == MOONBR_COMMAND_TERMINATE) break; 1.6 listener = moonbr_child_receive_pointer(MOONBR_FD_CONTROL); 1.7 - if (fd) moonbr_io_pushhandle(L, fd, 1, controlmsg == MOONBR_SOCKETTYPE_NETWORK); 1.8 + if (fd) moonbr_io_pushhandle(L, fd, controlmsg == MOONBR_SOCKETTYPE_NETWORK); 1.9 lua_rawgetp(L, LUA_REGISTRYINDEX, moonbr_luakey_connect_func(pool)); 1.10 if (!fd) { 1.11 lua_newtable(L);
2.1 --- a/moonbridge_io.c Tue Apr 07 04:08:41 2015 +0200 2.2 +++ b/moonbridge_io.c Tue Apr 07 22:17:13 2015 +0200 2.3 @@ -25,9 +25,9 @@ 2.4 2.5 typedef struct { 2.6 int fd; 2.7 - int issocket; 2.8 - int canshutdown; 2.9 - int shutwr; 2.10 + int useshutdown; 2.11 + int finished; 2.12 + int closed; 2.13 int nonblocking; 2.14 int readerr; 2.15 int readbufcnt; 2.16 @@ -65,7 +65,7 @@ 2.17 2.18 static void moonbr_io_handle_set_linger(lua_State *L, moonbr_io_handle_t *handle, int timeout) { 2.19 struct linger lingerval = { 0, }; 2.20 - if (!handle->issocket) return; 2.21 + if (!handle->useshutdown) return; 2.22 if (timeout >= 0) { 2.23 lingerval.l_onoff = 1; 2.24 lingerval.l_linger = timeout; 2.25 @@ -95,7 +95,8 @@ 2.26 terminator = terminatorstr[0]; 2.27 } 2.28 lua_settop(L, 1); /* return handle on drain, terminator string may be garbage collected */ 2.29 - if (handle->fd < 0) luaL_error(L, "Attempt to read from a closed I/O handle"); 2.30 + if (handle->closed) luaL_error(L, "Attempt to read from a closed I/O handle"); 2.31 + if (handle->fd < 0) goto moonbr_io_read_impl_eof; /* fake EOF to simulate shutdown */ 2.32 if (handle->readerr) { 2.33 lua_pushnil(L); 2.34 lua_pushliteral(L, "Previous read error"); 2.35 @@ -147,6 +148,7 @@ 2.36 handle->readbufcnt = 0; 2.37 if (!drain) { 2.38 if (!luabufcnt && result == 0) { 2.39 + moonbr_io_read_impl_eof: 2.40 lua_pushboolean(L, 0); 2.41 lua_pushliteral(L, "End of file"); 2.42 return 2; 2.43 @@ -182,8 +184,8 @@ 2.44 size_t written; 2.45 ssize_t result; 2.46 handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); 2.47 - if (handle->fd < 0) luaL_error(L, "Attempt to write to a closed I/O handle"); 2.48 - if (handle->shutwr) luaL_error(L, "Attempt to write to a finished I/O handle"); 2.49 + if (handle->closed) luaL_error(L, "Attempt to write to a closed I/O handle"); 2.50 + if (handle->finished) luaL_error(L, "Attempt to write to a finished I/O handle"); 2.51 if (handle->writeerr) { 2.52 lua_pushnil(L); 2.53 lua_pushliteral(L, "Previous write error"); 2.54 @@ -295,34 +297,44 @@ 2.55 static int moonbr_io_finish(lua_State *L) { 2.56 moonbr_io_handle_t *handle; 2.57 handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); 2.58 - if (handle->fd < 0) luaL_error(L, "Attempt to finish a closed I/O handle"); 2.59 - if (handle->shutwr) luaL_error(L, "Attempt to finish a finished I/O handle"); 2.60 - handle->shutwr = 1; 2.61 - if (handle->canshutdown) { 2.62 - if (handle->writeleft) { 2.63 - lua_pushcfunction(L, moonbr_io_flush); 2.64 - lua_pushvalue(L, 1); 2.65 - lua_call(L, 1, 2); 2.66 - if (!lua_toboolean(L, -2)) return 2; 2.67 + if (handle->closed) luaL_error(L, "Attempt to finish a closed I/O handle"); 2.68 + if (handle->finished) luaL_error(L, "Attempt to finish a finished I/O handle"); 2.69 + if (handle->writeleft) { 2.70 + lua_pushcfunction(L, moonbr_io_flush); 2.71 + lua_pushvalue(L, 1); 2.72 + lua_call(L, 1, 2); 2.73 + if (!lua_toboolean(L, -2)) { 2.74 + handle->finished = 1; 2.75 + return 2; 2.76 } 2.77 + } 2.78 + handle->finished = 1; 2.79 + if (handle->useshutdown) { 2.80 if (shutdown(handle->fd, SHUT_WR)) { 2.81 moonbr_io_errmsg(); 2.82 lua_pushnil(L); 2.83 lua_pushstring(L, errmsg); 2.84 return 2; 2.85 } 2.86 + } else { 2.87 + if (close(handle->fd)) { 2.88 + moonbr_io_errmsg(); 2.89 + handle->fd = -1; 2.90 + lua_pushnil(L); 2.91 + lua_pushstring(L, errmsg); 2.92 + return 2; 2.93 + } 2.94 + handle->fd = -1; /* fake EOF on read */ 2.95 } 2.96 lua_pushboolean(L, 1); 2.97 return 1; 2.98 } 2.99 2.100 -static int moonbr_io_close(lua_State *L) { 2.101 +static int moonbr_io_close_impl(lua_State *L, int reset) { 2.102 moonbr_io_handle_t *handle; 2.103 - int timeout; 2.104 handle = luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); 2.105 - timeout = luaL_optinteger(L, 2, -1); 2.106 - if (handle->fd < 0) luaL_error(L, "Attempt to close a closed I/O handle"); 2.107 - if (timeout != 0) { 2.108 + if (handle->closed) luaL_error(L, "Attempt to close a closed I/O handle"); 2.109 + if (!reset) { 2.110 if (handle->writeleft) { 2.111 lua_pushcfunction(L, moonbr_io_flush); 2.112 lua_pushvalue(L, 1); 2.113 @@ -333,14 +345,16 @@ 2.114 return 2; 2.115 } 2.116 } 2.117 - moonbr_io_handle_set_linger(L, handle, timeout); 2.118 + moonbr_io_handle_set_linger(L, handle, -1); 2.119 } 2.120 - if (close(handle->fd)) { 2.121 - moonbr_io_errmsg(); 2.122 - handle->fd = -1; 2.123 - lua_pushnil(L); 2.124 - lua_pushstring(L, errmsg); 2.125 - return 2; 2.126 + if (handle->fd >= 0) { 2.127 + if (close(handle->fd)) { 2.128 + moonbr_io_errmsg(); 2.129 + handle->fd = -1; 2.130 + lua_pushnil(L); 2.131 + lua_pushstring(L, errmsg); 2.132 + return 2; 2.133 + } 2.134 } 2.135 handle->fd = -1; 2.136 lua_pushboolean(L, 1); 2.137 @@ -348,14 +362,12 @@ 2.138 2.139 } 2.140 2.141 +static int moonbr_io_close(lua_State *L) { 2.142 + return moonbr_io_close_impl(L, 0); 2.143 +} 2.144 + 2.145 static int moonbr_io_reset(lua_State *L) { 2.146 - luaL_checkudata(L, 1, MOONBR_IO_HANDLE_MT_REGKEY); 2.147 - lua_settop(L, 1); 2.148 - lua_pushcfunction(L, moonbr_io_close); 2.149 - lua_insert(L, 1); 2.150 - lua_pushinteger(L, 0); 2.151 - lua_call(L, 2, LUA_MULTRET); 2.152 - return lua_gettop(L); 2.153 + return moonbr_io_close_impl(L, 1); 2.154 } 2.155 2.156 static int moonbr_io_gc(lua_State *L) { 2.157 @@ -381,13 +393,13 @@ 2.158 } 2.159 } 2.160 2.161 -void moonbr_io_pushhandle(lua_State *L, int fd, int issocket, int canshutdown) { 2.162 +void moonbr_io_pushhandle(lua_State *L, int fd, int useshutdown) { 2.163 moonbr_io_handle_t *handle; 2.164 handle = lua_newuserdata(L, sizeof(moonbr_io_handle_t)); 2.165 handle->fd = fd; 2.166 - handle->issocket = issocket; 2.167 - handle->canshutdown = canshutdown; 2.168 - handle->shutwr = 0; 2.169 + handle->useshutdown = useshutdown; 2.170 + handle->finished = 0; 2.171 + handle->closed = 0; 2.172 handle->nonblocking = -1; 2.173 handle->readerr = 0; 2.174 handle->readbufcnt = 0;
3.1 --- a/moonbridge_io.h Tue Apr 07 04:08:41 2015 +0200 3.2 +++ b/moonbridge_io.h Tue Apr 07 22:17:13 2015 +0200 3.3 @@ -1,5 +1,5 @@ 3.4 3.5 -void moonbr_io_pushhandle(lua_State *L, int fd, int issocket, int canshutdown); 3.6 +void moonbr_io_pushhandle(lua_State *L, int fd, int useshutdown); 3.7 void moonbr_io_closehandle(lua_State *L, int idx, int timeout); 3.8 int luaopen_moonbridge_io(lua_State *L); 3.9
4.1 --- a/reference.txt Tue Apr 07 04:08:41 2015 +0200 4.2 +++ b/reference.txt Tue Apr 07 22:17:13 2015 +0200 4.3 @@ -52,23 +52,19 @@ 4.4 a single socket object as argument, which is described below: 4.5 4.6 4.7 -### socket:close(timeout) 4.8 +### socket:close() 4.9 4.10 Closes the socket connection (input and output stream) by flushing all data and 4.11 -sending a TCP FIN packet. If the timeout value is non-nil but zero, a TCP RST 4.12 -is sent instead. If a positive timeout value is given and if the remote peer 4.13 -doesn't respond with a TCP FIN within the given time, a TCP RST is sent in 4.14 -addition to the previously sent TCP FIN packet. If the timeout value is nil or 4.15 -negative, the call returns immediately and the operating system will wait for 4.16 -the peer's TCP FIN packet. 4.17 +sending a TCP FIN packet. 4.18 4.19 Returns true on success, or nil plus error message in case of an I/O error. 4.20 Using this method on sockets that have already been closed (or reset) will 4.21 throw an error. 4.22 4.23 Warning: Pending data on the input stream may cause connection aborts (TCP RST) 4.24 -depending on the particular operating system used. All pending input data 4.25 -should have been read (or drained) before calling socket:close(). 4.26 +when network connections are used. All pending input data should have been read 4.27 +(or drained) before calling socket:close(). Use socket:finish() to send a 4.28 +TCP FIN packet to the peer before waiting for EOF from the peer. 4.29 4.30 4.31 ### socket:drain(maxlen, terminator) 4.32 @@ -91,6 +87,17 @@ 4.33 second result value) are returned. 4.34 4.35 4.36 +### socket:finish() 4.37 + 4.38 +Sends a TCP FIN packet to indicate EOF on write stream. Subsequent reads are 4.39 +still possible. When there is no more input data to be read, the connection 4.40 +should finally be closed with socket:close(). 4.41 + 4.42 +In case of local sockets (Unix Domain Sockets), socket:finish() simply closes 4.43 +the underlying socket and emulates EOF on subsequent reads. Also in this case, 4.44 +the connection should be finally closed with socket:close(). 4.45 + 4.46 + 4.47 ### socket:flush(...) 4.48 4.49 Same as socket:write(...) but additionally flushes the socket (i.e. all pending