# HG changeset patch # User jbe # Date 1425915775 -3600 # Node ID f2efab1ba3d067c31251f41385bdbad31e0522d1 # Parent 0bb356c04f6bdd398f9f3ba140163744643a9e21 Methods :close(), :cancel(), and :readuntil(...) do not throw I/O errors but return error message as second return value after nil diff -r 0bb356c04f6b -r f2efab1ba3d0 moonbridge.c --- a/moonbridge.c Sun Mar 08 01:09:28 2015 +0100 +++ b/moonbridge.c Mon Mar 09 16:42:55 2015 +0100 @@ -808,13 +808,6 @@ } } -/* Throws a Lua error message with an error string for errno appended to it */ -static void moonbr_child_lua_errno_error(lua_State *L, char *message) { - char errmsg[MOONBR_MAXSTRERRORLEN]; - strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ - luaL_error(L, "%s: %s", message, errmsg); -} - /* Closes the input stream from peer unless it has already been closed */ static int moonbr_child_close_peersocket_inputstream( int cleanshut, /* nonzero = use shutdown() if applicable */ @@ -984,16 +977,24 @@ luaL_Stream *stream = lua_touserdata(L, 1); if (stream == moonbr_child_peersocket_inputstream) { if (moonbr_child_close_peersocket_inputstream(1, 0)) { /* don't mark as closed as it's done by Lua */ - moonbr_child_lua_errno_error(L, "Could not close input stream"); + char errmsg[MOONBR_MAXSTRERRORLEN]; + strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ + lua_pushnil(L); + lua_pushfstring(L, "Could not close input stream from peer: %s", errmsg); + return 2; } } else if (stream == moonbr_child_peersocket_outputstream) { if (moonbr_child_close_peersocket_outputstream(1, 0)) { /* don't mark as closed as it's done by Lua */ - moonbr_child_lua_errno_error(L, "Could not close output stream"); + char errmsg[MOONBR_MAXSTRERRORLEN]; + strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ + lua_pushnil(L); + lua_pushfstring(L, "Could not close output stream to peer: %s", errmsg); + return 2; } } else { luaL_argerror(L, 1, "Not a connection socket"); } - lua_pushboolean(L, 1); // TODO: return nil or false on error instead of throwing error + lua_pushboolean(L, 1); return 1; } @@ -1009,9 +1010,13 @@ luaL_error(L, "Connection with peer has already been explicitly closed"); } if (moonbr_child_close_peersocket(timeout)) { - moonbr_child_lua_errno_error(L, "Could not close socket connection with peer"); + char errmsg[MOONBR_MAXSTRERRORLEN]; + strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ + lua_pushnil(L); + lua_pushfstring(L, "Could not close socket connection with peer: %s", errmsg); + return 2; } - lua_pushboolean(L, 1); // TODO: return nil or false on error instead of throwing error + lua_pushboolean(L, 1); return 1; } @@ -1021,9 +1026,13 @@ luaL_error(L, "Connection with peer has already been explicitly closed"); } if (moonbr_child_cancel_peersocket()) { - moonbr_child_lua_errno_error(L, "Could not cancel socket connection with peer"); + char errmsg[MOONBR_MAXSTRERRORLEN]; + strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ + lua_pushnil(L); + lua_pushfstring(L, "Could not cancel socket connection with peer: %s", errmsg); + return 2; } - lua_pushboolean(L, 1); // TODO: return nil or false on error instead of throwing error + lua_pushboolean(L, 1); return 1; } @@ -2245,10 +2254,12 @@ while (maxlen > 0 ? maxlen-- : maxlen) { byte = fgetc(file); if (byte == EOF) { - if (ferror(file)) { // TODO: return nil or false on error instead of throwing error + if (ferror(file)) { char errmsg[MOONBR_MAXSTRERRORLEN]; strerror_r(errno, errmsg, MOONBR_MAXSTRERRORLEN); /* use thread-safe call in case child created threads */ - luaL_error(L, "%s", errmsg); + lua_pushnil(L); + lua_pushstring(L, errmsg); + return 2; } else { break; } diff -r 0bb356c04f6b -r f2efab1ba3d0 reference.txt --- a/reference.txt Sun Mar 08 01:09:28 2015 +0100 +++ b/reference.txt Mon Mar 09 16:42:55 2015 +0100 @@ -31,7 +31,9 @@ ### socket:cancel() Closes the socket connection by sending a TCP RST package if possible to -indicate error condition. +indicate error condition. Returns true on success, or nil plus error message in +case of an I/O error. Using this method on sockets that have already been +closed (or canceled) will throw an error. Warning: Previously sent (and flushed) data may be lost during transmission. @@ -39,8 +41,9 @@ ### socket:close(timeout) Closes the socket connection (input and output stream) by flushing all data and -sending a TCP FIN package. Performs no operation if stream has already been -closed. +sending a TCP FIN package. Returns true on success, or nil plus error message +in case of an I/O error. Using this method on sockets that have already been +closed (or canceled) will throw an error. Warning: Pending data on the input stream may cause connection aborts (TCP RST) depending on the particular operating system used. All pending input data @@ -106,10 +109,12 @@ Reads as many bytes until a byte equal to the terminator value occurs. An optional maximum length may be specified. The terminating byte is included in -the return value (unless the maximum length would be exceeded). +the return value (unless the maximum length would be exceeded). On EOF, nil is +returned. In case of an I/O error, nil (as first result value) plus an error +message (as second result value) is returned. -Also available as :readuntil(...) method for any other Lua file handle -(including socket.input) +This method is also available as :readuntil(...) for any other Lua file handle +(including socket.input). ### socket.remote_ip4