Skip to content

Commit d97ea03

Browse files
author
blue-2357
committed
Revise WiFiClient::Write to handle EAGAIN (#240)
The send call may return EAGAIN. This indicates a recoverable error and a retry should be attempted. The current implementation treats this as a fatal error. Further, the current implementation strips the error code, setting it to 0, which prevents the caller from handling it directly. This change utilizes select to verify the socket is available prior to calling send and will retry on an EAGAIN condition.
1 parent 667cb22 commit d97ea03

File tree

1 file changed

+38
-6
lines changed

1 file changed

+38
-6
lines changed

libraries/WiFi/src/WiFiClient.cpp

+38-6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include <lwip/netdb.h>
2323
#include <errno.h>
2424

25+
#define WIFI_CLIENT_MAX_WRITE_RETRY (10)
26+
#define WIFI_CLIENT_SELECT_TIMEOUT_US (100000)
27+
2528
#undef connect
2629
#undef write
2730
#undef read
@@ -160,14 +163,43 @@ int WiFiClient::read()
160163

161164
size_t WiFiClient::write(const uint8_t *buf, size_t size)
162165
{
163-
if(!_connected) {
166+
int res =0;
167+
int retry = WIFI_CLIENT_MAX_WRITE_RETRY;
168+
int socketFileDescriptor = fd();
169+
170+
if(!_connected || (socketFileDescriptor < 0)) {
164171
return 0;
165172
}
166-
int res = send(sockfd, (void*)buf, size, MSG_DONTWAIT);
167-
if(res < 0) {
168-
log_e("%d", errno);
169-
stop();
170-
res = 0;
173+
174+
while(retry) {
175+
//use select to make sure the socket is ready for writing
176+
fd_set set;
177+
struct timeval tv;
178+
FD_ZERO(&set); // empties the set
179+
FD_SET(socketFileDescriptor, &set); // adds FD to the set
180+
tv.tv_sec = 0;
181+
tv.tv_usec = WIFI_CLIENT_SELECT_TIMEOUT_US;
182+
retry--;
183+
184+
if(select(socketFileDescriptor + 1, NULL, &set, NULL, &tv) < 0) {
185+
return 0;
186+
}
187+
188+
if(FD_ISSET(socketFileDescriptor, &set)) {
189+
res = send(socketFileDescriptor, (void*) buf, size, MSG_DONTWAIT);
190+
if(res < 0) {
191+
log_e("%d", errno);
192+
if(errno != EAGAIN) {
193+
//if resource was busy, can try again, otherwise give up
194+
stop();
195+
res = 0;
196+
retry = 0;
197+
}
198+
} else {
199+
//completed successfully
200+
retry = 0;
201+
}
202+
}
171203
}
172204
return res;
173205
}

0 commit comments

Comments
 (0)