mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-16 14:11:02 +00:00
fixed bug #35305: pcb may be freed too early on shutdown(WR)
This commit is contained in:
parent
593f75fc3b
commit
4d71f7270b
@ -62,6 +62,9 @@ HISTORY
|
|||||||
|
|
||||||
++ Bugfixes:
|
++ Bugfixes:
|
||||||
|
|
||||||
|
2012-01-22: Simon Goldschmidt
|
||||||
|
* tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR)
|
||||||
|
|
||||||
2012-01-21: Simon Goldschmidt
|
2012-01-21: Simon Goldschmidt
|
||||||
* tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb
|
* tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb
|
||||||
|
|
||||||
|
@ -298,7 +298,9 @@ tcp_close(struct tcp_pcb *pcb)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Causes all or part of a full-duplex connection of this PCB to be shut down.
|
* Causes all or part of a full-duplex connection of this PCB to be shut down.
|
||||||
* This doesn't deallocate the PCB!
|
* This doesn't deallocate the PCB unless shutting down both sides!
|
||||||
|
* Shutting down both sides is the same as calling tcp_close, so if it succeds,
|
||||||
|
* the PCB should not be referenced any more.
|
||||||
*
|
*
|
||||||
* @param pcb PCB to shutdown
|
* @param pcb PCB to shutdown
|
||||||
* @param shut_rx shut down receive side if this is != 0
|
* @param shut_rx shut down receive side if this is != 0
|
||||||
@ -313,28 +315,32 @@ tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx)
|
|||||||
return ERR_CONN;
|
return ERR_CONN;
|
||||||
}
|
}
|
||||||
if (shut_rx) {
|
if (shut_rx) {
|
||||||
/* shut down the receive side: free buffered data... */
|
/* shut down the receive side: set a flag not to receive any more data... */
|
||||||
|
pcb->flags |= TF_RXCLOSED;
|
||||||
|
if (shut_tx) {
|
||||||
|
/* shutting down the tx AND rx side is the same as closing for the raw API */
|
||||||
|
return tcp_close_shutdown(pcb, 1);
|
||||||
|
}
|
||||||
|
/* ... and free buffered data */
|
||||||
if (pcb->refused_data != NULL) {
|
if (pcb->refused_data != NULL) {
|
||||||
pbuf_free(pcb->refused_data);
|
pbuf_free(pcb->refused_data);
|
||||||
pcb->refused_data = NULL;
|
pcb->refused_data = NULL;
|
||||||
}
|
}
|
||||||
/* ... and set a flag not to receive any more data */
|
|
||||||
pcb->flags |= TF_RXCLOSED;
|
|
||||||
}
|
}
|
||||||
if (shut_tx) {
|
if (shut_tx) {
|
||||||
/* This can't happen twice since if it succeeds, the pcb's state is changed.
|
/* This can't happen twice since if it succeeds, the pcb's state is changed.
|
||||||
Only close in these states as the others directly deallocate the PCB */
|
Only close in these states as the others directly deallocate the PCB */
|
||||||
switch (pcb->state) {
|
switch (pcb->state) {
|
||||||
case SYN_RCVD:
|
case SYN_RCVD:
|
||||||
case ESTABLISHED:
|
case ESTABLISHED:
|
||||||
case CLOSE_WAIT:
|
case CLOSE_WAIT:
|
||||||
return tcp_close_shutdown(pcb, 0);
|
return tcp_close_shutdown(pcb, shut_rx);
|
||||||
default:
|
default:
|
||||||
/* don't shut down other states */
|
/* Not (yet?) connected, cannot shutdown the TX side as that would bring us
|
||||||
break;
|
into CLOSED state, where the PCB is deallocated. */
|
||||||
|
return ERR_CONN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* @todo: return another err_t if not in correct state or already shut? */
|
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,6 +316,12 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
} else if (recv_flags & TF_CLOSED) {
|
} else if (recv_flags & TF_CLOSED) {
|
||||||
/* The connection has been closed and we will deallocate the
|
/* The connection has been closed and we will deallocate the
|
||||||
PCB. */
|
PCB. */
|
||||||
|
if (!(pcb->flags & TF_RXCLOSED)) {
|
||||||
|
/* Connection closed although the application has only shut down the
|
||||||
|
tx side: call the PCB's err callback and indicate the closure to
|
||||||
|
ensure the application doesn't continue using the PCB. */
|
||||||
|
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD);
|
||||||
|
}
|
||||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user