I've investigated this further.
Invoking netstat -P on the PCB of the connection hanging yields there is data
to send, there is a window, but the REXMT timer is zero.
Following a hint of ws@, I investigated the PCB in question with gdb, and I'm
confused about the timers. The entry for the retransmit timer shows it has long
expired (i.e. c_time is much larger than kern.hardclock_ticks), and it has
fired, but is no longer pending (c_flags = 4).
Now I looked at the timer handling in tcp_output.c and tcp_timers.c and am
unsure how this can happen, as well as confused about the usage of the
TCP_TIMER_ISARMED macro. Browsing the source, I would get the impression that
this means "the timer is already running" while it's actually equivalent to
callout_active, i. e. callout_pending || callout_fired.
What's the reason for testing whether a callout caused by the retransmit
timer having expired has happened in the past before setting it again?
This looks completely broken to me, but that's most probably because of me,
not because of the code.
Can someone please enlighten me?