aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-17 08:02:04 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-17 08:02:04 +0000
commit02ef4e7daae6bef629dcb568052755fb85ed2efc (patch)
tree3001b5d4429626e086b457ade7a899428fbfeb34
parent076451c75336b30e6152bd5c02f355db39107f7d (diff)
downloadluasocket-02ef4e7daae6bef629dcb568052755fb85ed2efc.tar.gz
luasocket-02ef4e7daae6bef629dcb568052755fb85ed2efc.tar.bz2
luasocket-02ef4e7daae6bef629dcb568052755fb85ed2efc.zip
Trying to get rid of EINTR problems...
-rw-r--r--src/inet.c6
-rw-r--r--src/inet.h2
-rw-r--r--src/io.h1
-rw-r--r--src/socket.h2
-rw-r--r--src/tcp.c7
-rw-r--r--src/udp.c4
-rw-r--r--src/usocket.c59
-rw-r--r--src/wsocket.c7
8 files changed, 63 insertions, 25 deletions
diff --git a/src/inet.c b/src/inet.c
index f15a5a4..2334f53 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -181,7 +181,7 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
181* Tries to connect to remote address (address, port) 181* Tries to connect to remote address (address, port)
182\*-------------------------------------------------------------------------*/ 182\*-------------------------------------------------------------------------*/
183const char *inet_tryconnect(p_sock ps, const char *address, 183const char *inet_tryconnect(p_sock ps, const char *address,
184 unsigned short port) 184 unsigned short port, int timeout)
185{ 185{
186 struct sockaddr_in remote; 186 struct sockaddr_in remote;
187 const char *err; 187 const char *err;
@@ -197,14 +197,12 @@ const char *inet_tryconnect(p_sock ps, const char *address,
197 memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr)); 197 memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr));
198 } 198 }
199 } else remote.sin_family = AF_UNSPEC; 199 } else remote.sin_family = AF_UNSPEC;
200 sock_setblocking(ps); 200 err = sock_connect(ps, (SA *) &remote, sizeof(remote), timeout);
201 err = sock_connect(ps, (SA *) &remote, sizeof(remote));
202 if (err) { 201 if (err) {
203 sock_destroy(ps); 202 sock_destroy(ps);
204 *ps = SOCK_INVALID; 203 *ps = SOCK_INVALID;
205 return err; 204 return err;
206 } else { 205 } else {
207 sock_setnonblocking(ps);
208 return NULL; 206 return NULL;
209 } 207 }
210} 208}
diff --git a/src/inet.h b/src/inet.h
index b69e82d..08979c1 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -25,7 +25,7 @@
25 25
26void inet_open(lua_State *L); 26void inet_open(lua_State *L);
27const char *inet_tryconnect(p_sock ps, const char *address, 27const char *inet_tryconnect(p_sock ps, const char *address,
28 unsigned short port); 28 unsigned short port, int timeout);
29const char *inet_trybind(p_sock ps, const char *address, 29const char *inet_trybind(p_sock ps, const char *address,
30 unsigned short port, int backlog); 30 unsigned short port, int backlog);
31const char *inet_trycreate(p_sock ps, int type); 31const char *inet_trycreate(p_sock ps, int type);
diff --git a/src/io.h b/src/io.h
index f56094a..33675d8 100644
--- a/src/io.h
+++ b/src/io.h
@@ -24,6 +24,7 @@ enum {
24 IO_CLOSED, /* the connection has been closed */ 24 IO_CLOSED, /* the connection has been closed */
25 IO_ERROR, /* something wrong... */ 25 IO_ERROR, /* something wrong... */
26 IO_REFUSED, /* transfer has been refused */ 26 IO_REFUSED, /* transfer has been refused */
27 IO_RETRY, /* please try again */
27 IO_LIMITED /* maximum number of bytes reached */ 28 IO_LIMITED /* maximum number of bytes reached */
28}; 29};
29 30
diff --git a/src/socket.h b/src/socket.h
index cea9e0d..aeadff0 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -34,7 +34,7 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol);
34void sock_destroy(p_sock ps); 34void sock_destroy(p_sock ps);
35int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, 35int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
36 int timeout); 36 int timeout);
37const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len); 37const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout);
38const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len); 38const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len);
39void sock_listen(p_sock ps, int backlog); 39void sock_listen(p_sock ps, int backlog);
40void sock_shutdown(p_sock ps, int how); 40void sock_shutdown(p_sock ps, int how);
diff --git a/src/tcp.c b/src/tcp.c
index a67b44a..fe09e8c 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -257,7 +257,10 @@ static int meth_connect(lua_State *L)
257 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 257 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
258 const char *address = luaL_checkstring(L, 2); 258 const char *address = luaL_checkstring(L, 2);
259 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 259 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
260 const char *err = inet_tryconnect(&tcp->sock, address, port); 260 p_tm tm = &tcp->tm;
261 const char *err;
262 tm_markstart(tm);
263 err = inet_tryconnect(&tcp->sock, address, port, tm_getfailure(tm));
261 if (err) { 264 if (err) {
262 lua_pushnil(L); 265 lua_pushnil(L);
263 lua_pushstring(L, err); 266 lua_pushstring(L, err);
@@ -326,7 +329,7 @@ static int meth_getsockname(lua_State *L)
326\*-------------------------------------------------------------------------*/ 329\*-------------------------------------------------------------------------*/
327static int meth_settimeout(lua_State *L) 330static int meth_settimeout(lua_State *L)
328{ 331{
329 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); 332 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
330 return tm_meth_settimeout(L, &tcp->tm); 333 return tm_meth_settimeout(L, &tcp->tm);
331} 334}
332 335
diff --git a/src/udp.c b/src/udp.c
index 21730ab..eb2cea0 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -335,12 +335,14 @@ static int meth_settimeout(lua_State *L)
335static int meth_setpeername(lua_State *L) 335static int meth_setpeername(lua_State *L)
336{ 336{
337 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 337 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
338 p_tm tm = &udp->tm;
338 const char *address = luaL_checkstring(L, 2); 339 const char *address = luaL_checkstring(L, 2);
339 int connecting = strcmp(address, "*"); 340 int connecting = strcmp(address, "*");
340 unsigned short port = connecting ? 341 unsigned short port = connecting ?
341 (unsigned short) luaL_checknumber(L, 3) : 342 (unsigned short) luaL_checknumber(L, 3) :
342 (unsigned short) luaL_optnumber(L, 3, 0); 343 (unsigned short) luaL_optnumber(L, 3, 0);
343 const char *err = inet_tryconnect(&udp->sock, address, port); 344 const char *err;
345 err = inet_tryconnect(&udp->sock, address, port, tm_getfailure(tm));
344 if (err) { 346 if (err) {
345 lua_pushnil(L); 347 lua_pushnil(L);
346 lua_pushstring(L, err); 348 lua_pushstring(L, err);
diff --git a/src/usocket.c b/src/usocket.c
index 89be85e..9fcf4e8 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -2,6 +2,17 @@
2* Socket compatibilization module for Unix 2* Socket compatibilization module for Unix
3* LuaSocket toolkit 3* LuaSocket toolkit
4* 4*
5* We are now treating EINTRs, but if an interrupt happens in the middle of
6* a select function call, we don't guarantee values timeouts anymore.
7* It's not a big deal, since we are not real-time anyways.
8*
9* We also exchanged the order of the calls to send/recv and select.
10* The idea is that the outer loop (whoever is calling sock_send/recv)
11* will call the function again if we didn't time out, so we can
12* call write and then select only if it fails. This moves the penalty
13* to when data is not available, maximizing the bandwidth if data is
14* always available.
15*
5* RCS ID: $Id$ 16* RCS ID: $Id$
6\*=========================================================================*/ 17\*=========================================================================*/
7#include <string.h> 18#include <string.h>
@@ -49,10 +60,27 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol)
49/*-------------------------------------------------------------------------*\ 60/*-------------------------------------------------------------------------*\
50* Connects or returns error message 61* Connects or returns error message
51\*-------------------------------------------------------------------------*/ 62\*-------------------------------------------------------------------------*/
52const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) 63const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout)
53{ 64{
54 if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); 65 t_sock sock = *ps;
55 else return NULL; 66 if (sock == SOCK_INVALID) return "closed";
67 if (connect(sock, addr, addr_len) < 0) {
68 struct timeval tv;
69 fd_set wfds, efds;
70 int err;
71 tv.tv_sec = timeout / 1000;
72 tv.tv_usec = (timeout % 1000) * 1000;
73 FD_ZERO(&wfds); FD_ZERO(&efds);
74 FD_SET(sock, &wfds); FD_SET(sock, &efds);
75 do err = select(sock+1, NULL, &wfds, &efds, timeout >= 0 ? &tv : NULL);
76 while (err < 0 && errno == EINTR);
77 if (err <= 0) return "timeout";
78 if (FD_ISSET(sock, &efds)) {
79 char dummy;
80 recv(sock, &dummy, 0, 0);
81 return sock_connectstrerror();
82 } else return NULL;
83 } else return NULL;
56} 84}
57 85
58/*-------------------------------------------------------------------------*\ 86/*-------------------------------------------------------------------------*\
@@ -91,14 +119,16 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
91 SA dummy_addr; 119 SA dummy_addr;
92 socklen_t dummy_len; 120 socklen_t dummy_len;
93 fd_set fds; 121 fd_set fds;
122 int err;
94 if (sock == SOCK_INVALID) return IO_CLOSED; 123 if (sock == SOCK_INVALID) return IO_CLOSED;
95 tv.tv_sec = timeout / 1000; 124 tv.tv_sec = timeout / 1000;
96 tv.tv_usec = (timeout % 1000) * 1000; 125 tv.tv_usec = (timeout % 1000) * 1000;
97 FD_ZERO(&fds); 126 FD_ZERO(&fds);
98 FD_SET(sock, &fds); 127 FD_SET(sock, &fds);
99 *pa = SOCK_INVALID; 128 *pa = SOCK_INVALID;
100 if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) 129 do err = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
101 return IO_TIMEOUT; 130 while (err < 0 && errno == EINTR);
131 if (err <= 0) return IO_TIMEOUT;
102 if (!addr) addr = &dummy_addr; 132 if (!addr) addr = &dummy_addr;
103 if (!addr_len) addr_len = &dummy_len; 133 if (!addr_len) addr_len = &dummy_len;
104 *pa = accept(sock, addr, addr_len); 134 *pa = accept(sock, addr, addr_len);
@@ -108,12 +138,6 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
108 138
109/*-------------------------------------------------------------------------*\ 139/*-------------------------------------------------------------------------*\
110* Send with timeout 140* Send with timeout
111* Here we exchanged the order of the calls to write and select
112* The idea is that the outer loop (whoever is calling sock_send)
113* will call the function again if we didn't time out, so we can
114* call write and then select only if it fails.
115* Should speed things up!
116* We are also treating EINTR and EPIPE errors.
117\*-------------------------------------------------------------------------*/ 141\*-------------------------------------------------------------------------*/
118int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, 142int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
119 int timeout) 143 int timeout)
@@ -138,7 +162,8 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
138 tv.tv_usec = (timeout % 1000) * 1000; 162 tv.tv_usec = (timeout % 1000) * 1000;
139 FD_ZERO(&fds); 163 FD_ZERO(&fds);
140 FD_SET(sock, &fds); 164 FD_SET(sock, &fds);
141 ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); 165 do ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ?&tv : NULL);
166 while (ret < 0 && errno == EINTR);
142 /* tell the caller to call us again because there is more data */ 167 /* tell the caller to call us again because there is more data */
143 if (ret > 0) return IO_DONE; 168 if (ret > 0) return IO_DONE;
144 /* tell the caller there was no data before timeout */ 169 /* tell the caller there was no data before timeout */
@@ -178,7 +203,8 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
178 tv.tv_usec = (timeout % 1000) * 1000; 203 tv.tv_usec = (timeout % 1000) * 1000;
179 FD_ZERO(&fds); 204 FD_ZERO(&fds);
180 FD_SET(sock, &fds); 205 FD_SET(sock, &fds);
181 ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ? &tv : NULL); 206 do ret = select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL);
207 while (ret < 0 && errno == EINTR);
182 /* tell the caller to call us again because there is more data */ 208 /* tell the caller to call us again because there is more data */
183 if (ret > 0) return IO_DONE; 209 if (ret > 0) return IO_DONE;
184 /* tell the caller there was no data before timeout */ 210 /* tell the caller there was no data before timeout */
@@ -199,7 +225,6 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
199* will call the function again if we didn't time out, so we can 225* will call the function again if we didn't time out, so we can
200* call write and then select only if it fails. 226* call write and then select only if it fails.
201* Should speed things up! 227* Should speed things up!
202* We are also treating EINTR errors.
203\*-------------------------------------------------------------------------*/ 228\*-------------------------------------------------------------------------*/
204int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 229int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
205{ 230{
@@ -218,7 +243,8 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
218 tv.tv_usec = (timeout % 1000) * 1000; 243 tv.tv_usec = (timeout % 1000) * 1000;
219 FD_ZERO(&fds); 244 FD_ZERO(&fds);
220 FD_SET(sock, &fds); 245 FD_SET(sock, &fds);
221 ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 246 do ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
247 while (ret < 0 && errno == EINTR);
222 if (ret > 0) return IO_DONE; 248 if (ret > 0) return IO_DONE;
223 else return IO_TIMEOUT; 249 else return IO_TIMEOUT;
224 } else { 250 } else {
@@ -248,7 +274,8 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
248 tv.tv_usec = (timeout % 1000) * 1000; 274 tv.tv_usec = (timeout % 1000) * 1000;
249 FD_ZERO(&fds); 275 FD_ZERO(&fds);
250 FD_SET(sock, &fds); 276 FD_SET(sock, &fds);
251 ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 277 do ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
278 while (ret < 0 && errno == EINTR);
252 if (ret > 0) return IO_DONE; 279 if (ret > 0) return IO_DONE;
253 else return IO_TIMEOUT; 280 else return IO_TIMEOUT;
254 } else { 281 } else {
diff --git a/src/wsocket.c b/src/wsocket.c
index 30208b9..bf92a90 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -2,6 +2,13 @@
2* Socket compatibilization module for Win32 2* Socket compatibilization module for Win32
3* LuaSocket toolkit 3* LuaSocket toolkit
4* 4*
5* We also exchanged the order of the calls to send/recv and select.
6* The idea is that the outer loop (whoever is calling sock_send/recv)
7* will call the function again if we didn't time out, so we can
8* call write and then select only if it fails. This moves the penalty
9* to when data is not available, maximizing the bandwidth if data is
10* always available.
11*
5* RCS ID: $Id$ 12* RCS ID: $Id$
6\*=========================================================================*/ 13\*=========================================================================*/
7#include <string.h> 14#include <string.h>