Sat 20 Feb 2010 06:11:25 PM UTC, comment #9:
Fixed by not updating pcb->tmr after calling tcp_close() (i.e. in states FIN_WAIT_1, FIN_WAIT_2 and LAST_ACK.
|
Mon 15 Feb 2010 06:40:25 PM UTC, comment #8:
We should continue the discussion about close vs. shutdown in task #10088 and delay this bug until that task is done.
|
Wed 21 Oct 2009 11:20:43 AM UTC, comment #7:
Having close and shutdown is planned for 1.4.0, so this will be dependent on that.
|
Mon 19 Oct 2009 01:04:11 PM UTC, comment #6:
I think this is actually a subtle API change that should be considered carefully.
Currently we have a tcp_close that acts like a shutdown(SHUT_WR) and we have nothing that acts like close(). If you simply modify the timer handling, we'll then have tcp_close acting like close(), but then we won't have a shutdown(SHUT_WR).
As it stands now, a NO_SYS application can rely on receiving a final recv callback with NULL pbuf argument indicating that the remote end sent a FIN. Some applications may be relying on this behavior for cleanup of application state (mine does, for example).
IMO it would be preferable to have both a close and a shutdown as the two are distinct and both have valid uses. Naively, it seems like a simple flag would be sufficient to distinguish the two cases but I could be overlooking many details.
(Yes, I know that I originally filed this bug report but my understanding has become more, er, nuanced since April. :-)
|
Sun 18 Oct 2009 09:07:11 AM UTC, comment #5:
Would preventing to reset pcb->tmr in tcp_process for FIN_WAIT_2 and LAST_ACK states be enough to solve this?
|
Mon 06 Apr 2009 09:16:47 AM UTC, comment #4:
It is mean that we have timeout error in LAST_ACK state too.
|
Fri 03 Apr 2009 02:27:40 PM UTC, comment #3:
OK, that makes sense, thanks.
|
Fri 03 Apr 2009 01:48:16 PM UTC, comment #2:
True but there's only a single timer ("tmr") in the pcb and it gets updated for each segment received. So if the remote end continues to send data after we sent the FIN -- which is perfectly okay for it to do -- the session never times out.
Since the intent of tcp_close is to permanently disconnect (as opposed to "shutdown" semantics), then we should eventually force a connection close. Otherwise, resources on both sides could remain allocated indefinitely.
|
Thu 02 Apr 2009 02:20:15 PM UTC, comment #1:
There's some code in tcp_slowtmr() that seems to be intending to do this:
/* Check if this PCB has stayed too long in FIN-WAIT-2 */
if (pcb->state == FIN_WAIT_2) {
if ((u32_t)(tcp_ticks - pcb->tmr) >
TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {
++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: removing pcb stuck in FIN-WAIT-2\n"));
}
}
|
Wed 01 Apr 2009 01:16:18 PM UTC, original submission:
If an application calls tcp_close, this indicates that it no longer needs the connection (i.e. it's equivalent to closing the socket descriptor in Unix). Hence, after a FIN is sent to the peer, the TCP session should enter a state where it is guaranteed to be destroyed eventually. In the typical TCP implementation (see reference below), this is achieved by an additional FIN_WAIT_2 timer. There is no such mechanism in the current lwIP implementation -- the session and associated data structure may hang around forever if the remote peer doesn't send a FIN of its own.
From "TCP/IP Illustrated Volume 2", chapter 25, section 25.1, bullet 6 (http://my.safaribooksonline.com/020163354X/ch25):
"A FIN_WAIT_2 timer. When a connection moves from the FIN_WAIT_1 state to the FIN_WAIT_2 state (Figure 24.15) and the connection cannot receive any more data (implying the process called close, instead of taking advantage of TCP's half-close with shutdown), this timer is set to 10 minutes. When this timer expires it is reset to 75 seconds, and when it expires the second time the connection is dropped. The purpose of this timer is to avoid leaving a connection in the FIN_WAIT_2 state forever, if the other end never sends a FIN. (We don't show this timeout in Figure 24.15.)"
|