aboutsummaryrefslogtreecommitdiff
path: root/src/usocket.c
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 /src/usocket.c
parent076451c75336b30e6152bd5c02f355db39107f7d (diff)
downloadluasocket-02ef4e7daae6bef629dcb568052755fb85ed2efc.tar.gz
luasocket-02ef4e7daae6bef629dcb568052755fb85ed2efc.tar.bz2
luasocket-02ef4e7daae6bef629dcb568052755fb85ed2efc.zip
Trying to get rid of EINTR problems...
Diffstat (limited to 'src/usocket.c')
-rw-r--r--src/usocket.c59
1 files changed, 43 insertions, 16 deletions
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 {