summaryrefslogtreecommitdiff
path: root/extmod/modlwip.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2019-07-03 15:50:13 +1000
committerDamien George <damien.p.george@gmail.com>2019-07-03 15:50:13 +1000
commit1d6cb6357a2cde40822712211fb51c4a4bbe41cf (patch)
tree27ba5af3612a7138aaaa65b5a1690f81710d5dd9 /extmod/modlwip.c
parentef00048fed079c922a4e2bc9ce854cc3824e2bfc (diff)
extmod/modlwip: For TCP send keep trying tcp_write if it returns ERR_MEM
If tcp_write returns ERR_MEM then it's not a fatal error but instead means the caller should retry the write later on (and this is what lwIP's netconn API does). This fixes problems where a TCP send would raise OSError(ENOMEM) in situations where the TCP/IP stack is under heavy load. See eg issues #1897 and #1971.
Diffstat (limited to 'extmod/modlwip.c')
-rw-r--r--extmod/modlwip.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index 4127d21ad..aed69f920 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -668,7 +668,25 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
u16_t write_len = MIN(available, len);
- err_t err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY);
+ // If tcp_write returns ERR_MEM then there's currently not enough memory to
+ // queue the write, so wait and keep trying until it succeeds (with 10s limit).
+ // Note: if the socket is non-blocking then this code will actually block until
+ // there's enough memory to do the write, but by this stage we have already
+ // committed to being able to write the data.
+ err_t err;
+ for (int i = 0; i < 200; ++i) {
+ err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY);
+ if (err != ERR_MEM) {
+ break;
+ }
+ err = tcp_output(socket->pcb.tcp);
+ if (err != ERR_OK) {
+ break;
+ }
+ MICROPY_PY_LWIP_EXIT
+ mp_hal_delay_ms(50);
+ MICROPY_PY_LWIP_REENTER
+ }
// If the output buffer is getting full then send the data to the lower layers
if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) {