lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] event_callback in Sockets.c stuck in infinite loop


From: Niall Donovan
Subject: [lwip-users] event_callback in Sockets.c stuck in infinite loop
Date: Tue, 27 Aug 2013 14:37:03 +0100

Hi All,
   I'm new to the mailing list so forgive me if I haven't conformed to some existing rules (inserting code for example?!)

   I'm using an Altera NIOS2 port of lwIP 1.4.1 with freeRTOS as the OS. I'm using TCP/IP sockets to provide a connections between a GUI and the NIOS process on our test device. My GUI opens 2 socket connections to the NIOS, one on IP port 2000 and one on IP port 2001. The NIOS, using lwIP, can support connecting to 2 GUIs simultaneously, i.e. two socket connections can be open on IP port 2000 and two socket connections can be open on IP port 2001 at the same time. I have a task serving the 2 possible sockets on IP port 2000, a.k.a. 'simpleSocketServerTask', and another task serving the 2 possible sockets on IP port 2001, a.k.a. 'pushTask'. 

I'm calling sockets in blocking mode but using a timeout on the select() function to allow me to loop through my 2 possible connections to service any connection requests or received packets. I've listed my code for the simpleSocketServerTask below. The pushTask() is identical apart from the IP port number.

If only one GUI is connected, i.e. one socket connection on port 2000 and one on port 2001 then all is good and the link is stable, indefinitely. Once I connect the second GUI the links will fail anywhere from a 1-2 minutes to 30 minutes. When it fails it 'appears' as if the code is stuck in the event_callback() function in the sockets.c file. It is stuck in the 'for' loop just after the 'again:' label. The callback list pointer 'scb' == 0xFFFFFFFF, last_select_cb_ctr == select_cb_ctr and select_cb_list == 0xFFFFFFFF. In the NIOS 2 lwIP version I have there is an ASSERT command in the for loop that reads: 
LWIP_ASSERT("shit is hitting the fan!", (scb->next != (void*)0xffffffff));
 I don't understand why this is there or who put it there, but the wording worries me and it's obvious that a value of 0xFFFFFFFF is not a valid value to have for scb or select_cb_list. The assert is never triggered though!

I have confirmed that all my other OS threads are still functioning, but because the event_callback function will not terminate, the input path on the stack is stalled and at the point of failure I have used up all my TCIP_MSG_INPKT message entries (16) and pbufs (64). In normal use I only need 3 and 15 respectively.

When I get this failure I have configured the tcpip_thread to run at prioriy 3, simpleSocketServerTask at priority 3 and pushTask at priority 2. The input packet driver task was running at priority 3 also - a DMA transfer directly into a pre-allocated pbuf. 
If I move simpleSocketServerTask to priority 2 and pushTask to priority 1 my problem is resolved. Which is great, but I'd like to understand why. I would expect it to have worked with my original task priorities.  I suspect I have managed to corrupt the select_cb_list but I don't understand how given it is only modified in protected mode in the lwIP_select function!
Can anyone shed some light on this for me? Many thanks for your time in reading my problem.

Regards
Niall.

void simpleSocketServerTask()
{
#define SSS_NUM_CONNECTIONS 2
           #define SSS_PORT 2000 

int i,fd_listen, max_socket,retVal;
struct sockaddr_in addr;
struct  timeval select_timeout;
fd_set readfds;
static SSSConn conn[SSS_NUM_CONNECTIONS];
alt_u32 current_time = 0;
const char * sockName = "Cmd Socket";

fd_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("socket returned %d\n", fd_listen);
if (fd_listen < 0) {
perror("socket");
return;
}

addr.sin_family = AF_INET;
addr.sin_port = htons(SSS_PORT);
addr.sin_len = sizeof(addr);
addr.sin_addr.s_addr = INADDR_ANY;
printf("Binding socket\n");
if ((bind(fd_listen,(struct sockaddr *)&addr,sizeof(addr))) < 0)
{
perror("bind");
close(fd_listen);
return;
}

if (listen(fd_listen, SSS_NUM_CONNECTIONS) != 0)
{
perror("listen");
close(fd_listen);
return;
}

  for(i=0; i<SSS_NUM_CONNECTIONS; i++)
  {
  sss_reset_connection(&conn[i]);
  }
  printf("[sss_task] Simple Socket Server listening on port %d\n", SSS_PORT);

  while(1)
  {
    FD_ZERO(&readfds);
    //FD_ZERO(&writefds);
    FD_SET(fd_listen, &readfds);

    max_socket = fd_listen+1;

for(i=0; i<SSS_NUM_CONNECTIONS; i++)
{
if (conn[i].fd != -1)
{
 /* We're interested in reading any of our active sockets */
 FD_SET(conn[i].fd, &readfds);

 if (max_socket <= conn[i].fd)
 {
max_socket = conn[i].fd+1;
 }
}
}

// set a timeout on select
    select_timeout.tv_sec = 0;
    select_timeout.tv_usec = 80;
    select(max_socket, &readfds, NULL, NULL, &select_timeout);

    if (FD_ISSET(fd_listen, &readfds))
    {
      sss_handle_accept(fd_listen, conn, sockName);
    }

for(i=0; i<SSS_NUM_CONNECTIONS; i++)
    {
if ((conn[i].fd != -1) && FD_ISSET(conn[i].fd, &readfds))
{
sss_handle_receive(&conn[i]);
}
else
mssleep(10);

if (conn[i].fd != -1)
{
// Check if connection has timed out
current_time = alt_nticks();
if((current_time - conn[i].activity_time) >= SSS_KEEP_ALIVE_TIME)
{
conn[i].state = CLOSE;
conn[i].closeSock = CLOSE;
printf("[sss_task] timeout:closing connection\n");
close(conn[i].fd);
  sss_reset_connection(&conn[i]);
}
}
    }

  } /* while(1) */
}
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]