Port, board and/or hardware
Not port-specific: generic lwip path in extmod/modlwip.c, every MICROPY_PY_LWIP port. Measured on OpenMV RT1062 (i.MX RT1062, cyw43 WiFi).
MicroPython version
master at a129b2f, by reading extmod/modlwip.c. Measured on OpenMV release firmware v5.0.0, MicroPython v1.28.0-49, built 2026-07-02, 8 KB lwIP heap.
Reproduction
settimeout(0.5) socket sends to a slow peer; a second socket to another slow peer holds the lwIP heap in unacked segments.
tcp_write returns ERR_MEM while tcp_sndbuf still reports room.
sock.send(buf) blocks in lwip_tcp_send past 0.5 s.
One-file script, board and host side: #19705, "Test", phase 2.
Expected behaviour
sock.send() raises OSError(ETIMEDOUT) at the socket timeout, as the tcp_sndbuf == 0 wait in the same function already does.
Observed behaviour
The ERR_MEM for (;;) loop in lwip_tcp_send never reads socket->timeout. It ends on tcp_write success or at 10 s with ENOMEM. On master it waits in poll_sockets(); on the v1.28.0 line in mp_hal_delay_ms(50).
Two readers at 20 KB/s, settimeout(0.5), 120 s: starved send() took 1651–3401 ms; 0 ETIMEDOUT, 0 ENOMEM.
Additional Information
Timed-socket case of #19704. Fixed by the second commit of #19705: ETIMEDOUT at the socket timeout, counted from call start; the 10 s limit stays for a socket with no timeout. Same test with the change (16 KB heap): 172 ETIMEDOUT, 0 ENOMEM, longest send() 504 ms.
Code of Conduct
Yes, I agree.
Port, board and/or hardware
Not port-specific: generic
lwippath inextmod/modlwip.c, everyMICROPY_PY_LWIPport. Measured on OpenMV RT1062 (i.MX RT1062, cyw43 WiFi).MicroPython version
masterat a129b2f, by readingextmod/modlwip.c. Measured on OpenMV release firmware v5.0.0, MicroPython v1.28.0-49, built 2026-07-02, 8 KB lwIP heap.Reproduction
settimeout(0.5)socket sends to a slow peer; a second socket to another slow peer holds the lwIP heap in unacked segments.tcp_writereturnsERR_MEMwhiletcp_sndbufstill reports room.sock.send(buf)blocks inlwip_tcp_sendpast 0.5 s.One-file script, board and host side: #19705, "Test", phase 2.
Expected behaviour
sock.send()raisesOSError(ETIMEDOUT)at the socket timeout, as thetcp_sndbuf == 0wait in the same function already does.Observed behaviour
The
ERR_MEMfor (;;)loop inlwip_tcp_sendnever readssocket->timeout. It ends ontcp_writesuccess or at 10 s withENOMEM. Onmasterit waits inpoll_sockets(); on the v1.28.0 line inmp_hal_delay_ms(50).Two readers at 20 KB/s,
settimeout(0.5), 120 s: starvedsend()took 1651–3401 ms; 0ETIMEDOUT, 0ENOMEM.Additional Information
Timed-socket case of #19704. Fixed by the second commit of #19705:
ETIMEDOUTat the socket timeout, counted from call start; the 10 s limit stays for a socket with no timeout. Same test with the change (16 KB heap): 172ETIMEDOUT, 0ENOMEM, longestsend()504 ms.Code of Conduct
Yes, I agree.