Hello,
I am using FreeRTOS TCP IP stack in my software to create a telnet TCP server. I discoverred that when ever I connect and disconnect a client I end up with fewer heap memory as before.
I monitored it using the vApplicationIdleHook() by printing out the current and minimum ever heap consumption to the console, whilest repeatedly connecting & disconnecting the client.
As a result I discoverred that a socket needs always 17.544 bytes of memory and I’m always missing 64 bytes after a re-connection.
Does somebody know if this may be related to the TCP/IP stack? I looked through my own code and could not find anything explaining the loss of these 64 bytes…
I’ll post the source code for accepting a new client below:
static void createTCPServerSocket( void *pvParameters )
{
BaseType_t retVal_os = 0;
uport_ctrl_t * pCtrl = (uport_ctrl_t *) pvParameters;
TickType_t xSocketTimeOut = portMAX_DELAY;
const BaseType_t xBacklog = pCtrl->numOfClients;
socklen_t xSize = sizeof( pCtrl->sockAdrListener );
event_client_accept_e queueIpClientCon;
//Open new listening socket
//***************************************
/* Attempt to open the socket. */
pCtrl->socketListener = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
if(pCtrl->socketListener == FREERTOS_INVALID_SOCKET)
{
//Send feedback to parent
queueIpClientCon = eErrIpStack;
xQueueSend(pCtrl->osQueue_clientAccept, &queueIpClientCon, 0);
//Auto-delete this task now as it got useless
vTaskDelete( NULL );
}
// Define for how long accept() will wait for a connection.
retVal_os = FreeRTOS_setsockopt( pCtrl->socketListener,
0, //currently unused parameter
FREERTOS_SO_RCVTIMEO,
&xSocketTimeOut,
sizeof(TickType_t) );
if(retVal_os != STACK_SUCCESS)
{
//Send feedback to parent
queueIpClientCon = eErrIpStack;
xQueueSend(pCtrl->osQueue_clientAccept, &queueIpClientCon, 0);
//Auto-delete this task now as it got useless
vTaskDelete( NULL );
}
// Set the listening port
pCtrl->sockAdrListener.sin_port = ( uint16_t ) pCtrl->port;
pCtrl->sockAdrListener.sin_port = FreeRTOS_htons( pCtrl->sockAdrListener.sin_port );
// Bind the socket to the port that the client RTOS task will send to.
retVal_os = FreeRTOS_bind( pCtrl->socketListener, &pCtrl->sockAdrListener, sizeof( struct freertos_sockaddr) );
if(retVal_os != STACK_SUCCESS)
{
//Send feedback to parent
queueIpClientCon = eErrIpStack;
xQueueSend(pCtrl->osQueue_clientAccept, &queueIpClientCon, 0);
//Auto-delete this task now as it got useless
vTaskDelete( NULL );
}
// Set the socket into a listening state so it can accept connections.
// The maximum number of simultaneous connections is limited to xBacklog.
retVal_os = FreeRTOS_listen( pCtrl->socketListener, xBacklog );
if(retVal_os != STACK_SUCCESS)
{
//Send feedback to parent
queueIpClientCon = eErrIpStack;
xQueueSend(pCtrl->osQueue_clientAccept, &queueIpClientCon, 0);
//Attempt graceful shutdown client socket
FreeRTOS_shutdown( pCtrl->socketClient, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketClient);
if(retVal_os == pdTRUE)
{
//Shutdown is complete and the socket can be safely closed.
FreeRTOS_closesocket( pCtrl->socketClient );
}
//Attempt graceful shutdown listener socket
FreeRTOS_shutdown( pCtrl->socketListener, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketListener);
if(retVal_os == pdTRUE)
{
//Shutdown is complete and the socket can be safely closed.
FreeRTOS_closesocket( pCtrl->socketListener );
}
//Auto-delete this task now as it got useless
vTaskDelete( NULL );
}
//Create a temporary Socket that holds the newly connected client just until the old connection has been shutdown
Socket_t tempSocket;
while(retVal_os == STACK_SUCCESS)
{
/* Wait for incoming connections. */
tempSocket = FreeRTOS_accept( pCtrl->socketListener, &pCtrl->sockAdrClient, &xSize);
if(tempSocket == FREERTOS_INVALID_SOCKET )
{
//Send feedback to parent
queueIpClientCon = eErrIpStack;
xQueueSend(pCtrl->osQueue_clientAccept, &queueIpClientCon, 0);
//Attempt graceful shutdown client socket
FreeRTOS_shutdown( pCtrl->socketClient, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketClient);
if(retVal_os == pdTRUE)
{
//Shutdown is complete and the socket can be safely closed.
FreeRTOS_closesocket( pCtrl->socketClient );
}
//Attempt graceful shutdown listener socket
FreeRTOS_shutdown( pCtrl->socketListener, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketListener);
if(retVal_os == pdTRUE)
{
//Shutdown is complete and the socket can be safely closed.
FreeRTOS_closesocket( pCtrl->socketListener );
}
//Auto-delete this task now as it got useless
vTaskDelete( NULL );
}
/* Shutdown the old client connection */
//Make sure that the old socket does not point to the new one which would lead to closing the new one!
//And make sure that there is no old socket as this would lead to closing a non-existent socket which in turn would blow the tcp/ip stack
if(pCtrl->socketClient != tempSocket && pCtrl->socketClient != NULL)
{
FreeRTOS_shutdown( pCtrl->socketClient, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketClient);
if(retVal_os == pdTRUE)
{
FreeRTOS_closesocket( pCtrl->socketClient );
}
}
/* Assign the new connection to the control struct */
pCtrl->socketClient = tempSocket;
//Send Queue that says that uportOpen() that a new client has been accepted
queueIpClientCon = eClientConnected;
// Create the set of sockets that will be passed into FreeRTOS_select().
pCtrl->socketSet = FreeRTOS_CreateSocketSet();
if(pCtrl->socketSet == NULL)
{
//Send feedback to parent
queueIpClientCon = eErrIpStack;
xQueueSend(pCtrl->osQueue_clientAccept, &queueIpClientCon, 0);
//Attempt graceful shutdown client socket
FreeRTOS_shutdown( pCtrl->socketClient, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketClient);
if(retVal_os == pdTRUE)
{
//Shutdown is complete and the socket can be safely closed.
FreeRTOS_closesocket( pCtrl->socketClient );
}
//Attempt graceful shutdown listener socket
FreeRTOS_shutdown( pCtrl->socketListener, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketListener);
if(retVal_os == pdTRUE)
{
//Shutdown is complete and the socket can be safely closed.
FreeRTOS_closesocket( pCtrl->socketListener );
}
//Auto-delete this task now as it got useless
vTaskDelete( NULL );
}
//Set up sockets
// Add the created socket to the set for the READ event.
FreeRTOS_FD_SET( pCtrl->socketClient, pCtrl->socketSet, eSELECT_READ );
//Add the created socket to the set for EXEPTIONAL events.
FreeRTOS_FD_SET( pCtrl->socketClient, pCtrl->socketSet, eSELECT_EXCEPT );
//Set receive Timeout to "no wait" as we will use select to pend on this socket
xSocketTimeOut = 0;
// Define for how long recv() will wait for a data.
retVal_os = FreeRTOS_setsockopt( pCtrl->socketClient,
0,//currently unused parameter
FREERTOS_SO_RCVTIMEO,
&xSocketTimeOut,
sizeof(TickType_t) );
// Define for how long send() will wait to send data.
retVal_os |= FreeRTOS_setsockopt( pCtrl->socketClient,
0,//currently unused parameter
FREERTOS_SO_SNDTIMEO,
&xSocketTimeOut,
sizeof(TickType_t) );
if(retVal_os != STACK_SUCCESS)
{
//Send feedback to parent
queueIpClientCon = eErrIpStack;
xQueueSend(pCtrl->osQueue_clientAccept, &queueIpClientCon, 0);
//Attempt graceful shutdown client socket
FreeRTOS_shutdown( pCtrl->socketClient, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketClient);
if(retVal_os == pdTRUE)
{
//Shutdown is complete and the socket can be safely closed.
FreeRTOS_closesocket( pCtrl->socketClient );
}
//Attempt graceful shutdown listener socket
FreeRTOS_shutdown( pCtrl->socketListener, FREERTOS_SHUT_RDWR );
//Sometimes FreeRTOS_shutdown() closes the socket right away, sometimes not - make sure the socket still exists before calling FreeRTOS_closesocket() to avoid an assert error
retVal_os = FreeRTOS_issocketconnected(pCtrl->socketListener);
if(retVal_os == pdTRUE)
{
//Shutdown is complete and the socket can be safely closed.
FreeRTOS_closesocket( pCtrl->socketListener );
}
//Auto-delete this task now as it got useless
vTaskDelete( NULL );
}
//Signal in control block that a new client connection is present
pCtrl->bClientConnectionUp = true;
//Send back to caller the status of the connection if something changed - either success or error without terminating this task though
xQueueSend(pCtrl->osQueue_clientAccept, &queueIpClientCon, 0);
} //while
//Auto-delete this task now
vTaskDelete( NULL );
}
Hopefully somebody know something about it.
Best Regards,