diff --git a/CHANGELOG b/CHANGELOG index 68f7af03..9d087324 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,7 +18,7 @@ HISTORY 2015-11-12: Dirk Ziegelmeier * Implement possibility to declare private memory pools. This is useful to - decouple some apps from the core (SNMP stack) or make contrib app useage + decouple some apps from the core (SNMP stack) or make contrib app usage simpler (httpserver_raw) 2015-10-09: Simon Goldschmidt @@ -302,6 +302,11 @@ HISTORY ++ Bugfixes: + 2013-03-17: Joel Cunningham + * api_msg.c: don't fail closing a socket/netconn when failing to allocate the + FIN segment; blocking the calling thread for a while is better than risking + leaking a netconn/socket (see bug #46701) + 2013-03-16: Joel Cunningham * tcp_out.c: reset rto timer on fast retransmission diff --git a/src/api/api_msg.c b/src/api/api_msg.c index d2ec46ea..fd5594bb 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -884,38 +884,33 @@ lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM) #endif /* LWIP_SO_LINGER */ } else { if (err == ERR_MEM) { - /* Closing failed because of memory shortage */ - if (netconn_is_nonblocking(conn)) { - /* Nonblocking close failed */ - close_finished = 1; - err = ERR_WOULDBLOCK; - } else { - /* Blocking close, check the timeout */ + /* Closing failed because of memory shortage, try again later. Even for + nonblocking netconns, we have to wait since no standard socket application + is prepared for close failing because of resource shortage. + Check the timeout: this is kind of an lwip addition to the standard sockets: + we wait for some time when failing to allocate a segment for the FIN */ #if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER - s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; - /* this is kind of an lwip addition to the standard sockets: we wait - for some time when failing to allocate a segment for the FIN */ + s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT; #if LWIP_SO_SNDTIMEO - if (conn->send_timeout > 0) { - close_timeout = conn->send_timeout; - } + if (conn->send_timeout > 0) { + close_timeout = conn->send_timeout; + } #endif /* LWIP_SO_SNDTIMEO */ #if LWIP_SO_LINGER - if (conn->linger >= 0) { - /* use linger timeout (seconds) */ - close_timeout = conn->linger * 1000U; - } + if (conn->linger >= 0) { + /* use linger timeout (seconds) */ + close_timeout = conn->linger * 1000U; + } #endif - if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { + if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) { #else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - if (conn->current_msg->msg.sd.polls_left == 0) { + if (conn->current_msg->msg.sd.polls_left == 0) { #endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ - close_finished = 1; - if (close) { - /* in this case, we want to RST the connection */ - tcp_abort(tpcb); - err = ERR_OK; - } + close_finished = 1; + if (close) { + /* in this case, we want to RST the connection */ + tcp_abort(tpcb); + err = ERR_OK; } } } else {