tcp data loss with recv()
When an application is reading data from a TCP socket using recv() until recv() returns 0, the data stream might be missing some data at the end. This leads to corrupted connections or loss of data.
The problem is in so_dequeue_msg(). Line numbers given from revision 907c2824.
- In line 715, data from the queue is read, protected by so_lock
- in line 723, the lock is released
- in line 922, the lock is reacquired
- in line 932, so_state is checked for a received FIN (SS_CANTRECVMORE)
- if a FIN is received, return, effectively returning 0 to the caller of recv()
- if not, check in line 944 if data arrived while the lock was not held
Line 944 helps for the case when data arrived while the lock was not held, but when data+FIN arrive during that time, the check for more data is skipped. This signals a proper connection teardown to the application without delivering all data. In all observed cases the last connection contained data along with the FIN.
The fix is to move the check from line 944 to line 928.