Summary: Missing locking in tcp_input()
Project: lwIP - A Lightweight TCP/IP stack
Submitted by: andrew_parlane
Submitted on: Thu 20 Jun 2019 09:28:56 PM UTC
Severity: 3 - Normal
Item Group: Crash Error
Assigned to: None
Discussion Lock: Any
Planned Release: None
lwIP version: Other
I've been debugging an issue in our application where if the devices is
sending TCP packets and at the same time receiving lots of UDP packets (I
think this is due to the number of interrupts more than anything else), then
LWIP crashes with an assert.
The assert it hits is in lwip_netconn_do_writemore(). Specifically:
It appears to be an ACK to a TCP message that was sent.
After adding some debug messages in, I find that on calling lwip_send() (with
a size of 512 bytes) from the main thread, we end up in
lwip_netconn_do_write() where msg->conn->current_msg is set. We then end up in
lwip_netconn_do_writemore() where tcp_write() is called with the full packet.
Offset is updated:
conn->current_msg->msg.w.offset += len;
Now msg.w.offset is 512, and msg.w.len is 512. Because we wrote everything
write_more is set to 0, and we exit the loop. Further down we check if
msg.w.offset == msg.w.len and if so, we set write_finished, and then clear
However, a context switch occurs between updating msg.w.offset, and clearing
conn->current_msg. If it switches to the ethernetif_rx thread and that
receives a TCP ACK, we end up back in lwip_netconn_do_writemore(), but at this
point we fail the assert, because msg.w.offset == msg.w.len.
In the second callstack (from lwip_send()) we end up in
tcpip_send_msg_wait_sem() which has the following code:
As Sylvain already said it, you're doing things wrong. Maybe you're passing
'ethernet_input' as input function to 'netif_add' when registering your
altera_tse_ethernetif when you should have passed 'tcpip_input'...