forked from nuttx/nuttx-update
There was a possible recursion that could eventually overflow the stack. The error occurred when closing the socket with inet_close() while a socket callback was still queued. When the socket callback was executed by devif_conn_event(), this resulted in a call to psock_send_eventhandler() with TCP_CLOSE flag set which then called tcp_lost_connection(). tcp_shutdown_monitor() then called tcp_callback() again, which again called psock_send_eventhandler(), and so on.... Noted by Pascal Speck. Solution is also similar to a solution proposed by Pascal Speck.
This commit is contained in:
parent
bc40403516
commit
cf5cba953d
5 changed files with 13 additions and 8 deletions
|
@ -102,18 +102,18 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
|
|||
* it is supposed to be in the device notification list.
|
||||
*/
|
||||
|
||||
if (dev)
|
||||
if (dev != NULL)
|
||||
{
|
||||
/* Find the callback structure in the device event list */
|
||||
|
||||
for (prev = NULL, curr = dev->d_devcb;
|
||||
curr && curr != cb;
|
||||
curr != NULL && curr != cb;
|
||||
prev = curr, curr = curr->nxtdev);
|
||||
|
||||
/* Remove the structure from the device event list */
|
||||
|
||||
DEBUGASSERT(curr);
|
||||
if (curr)
|
||||
if (curr != NULL)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
|
|
|
@ -97,11 +97,11 @@ static uint16_t tcp_poll_eventhandler(FAR struct net_driver_s *dev,
|
|||
|
||||
ninfo("flags: %04x\n", flags);
|
||||
|
||||
DEBUGASSERT(!info || (info->psock && info->fds));
|
||||
DEBUGASSERT(info == NULL || (info->psock != NULL && info->fds != NULL));
|
||||
|
||||
/* 'priv' might be null in some race conditions (?) */
|
||||
|
||||
if (info)
|
||||
if (info != NULL)
|
||||
{
|
||||
pollevent_t eventset = 0;
|
||||
|
||||
|
|
|
@ -511,7 +511,12 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
|
|||
{
|
||||
ninfo("Lost connection: %04x\n", flags);
|
||||
|
||||
if (psock->s_conn != NULL)
|
||||
/* We could get here recursively through the callback actions of
|
||||
* tcp_lost_connection(). So don't repeat that action if we have
|
||||
* already been disconnected.
|
||||
*/
|
||||
|
||||
if (psock->s_conn != NULL && _SS_ISCONNECTED(psock->s_flags))
|
||||
{
|
||||
/* Report not connected */
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
|||
/* Allocate a TCP/IP callback structure */
|
||||
|
||||
cb = udp_callback_alloc(info->dev, conn);
|
||||
if (!cb)
|
||||
if (cb == NULL)
|
||||
{
|
||||
ret = -EBUSY;
|
||||
goto errout_with_lock;
|
||||
|
|
|
@ -195,7 +195,7 @@ static int usrsock_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
|
|||
/* Allocate a usrsock callback structure */
|
||||
|
||||
cb = devif_callback_alloc(NULL, &conn->list);
|
||||
if (!cb)
|
||||
if (cb == NULL)
|
||||
{
|
||||
ret = -EBUSY;
|
||||
kmm_free(info); /* fds->priv not set, so we need to free info here. */
|
||||
|
|
Loading…
Reference in a new issue