This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

fdShare() increase HeapMemory

Hello,

I am working on a shared socket solution where one task sends and one task receives data from a shared socket. I used the contest.c for the starting point and I realized that something is wrong with fdshare(). Each time when I instantiate a new rx and tx tasks and using fdShare in them, the HeapMemory is increasing more and more. 

Could you help me why? 

I have attached the whole project. For the tests you can use the tcpSendReceive.exe in the ti package.

Some hint: When I remove the fdShare from the code, I can run it without any error for a while. 

Looking forward your kind reply,

And here is the code also,

#include <string.h>

#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>

#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/drivers/GPIO.h>

#include <ti/sysbios/knl/Mailbox.h>
#include <xdc/cfg/global.h>



/* NDK BSD support */
#include <sys/socket.h>

/* Example/Board Header file */
#include "Board.h"

#define TCPPACKETSIZE 256
#define NUMTCPWORKERS 3


typedef struct mbdata{
	uint8_t code;
	uint8_t buff[TCPPACKETSIZE];
}Mbdata_t;

/*
 *  ======== tcpWorker ========
 *  Task to handle TCP connection. Can be multiple Tasks running
 *  this function.
 */
Void tcpWorker(UArg arg0, UArg arg1)
{


    int  clientfd = (int)arg0;
    int  bytesRcvd;
    char buffer[TCPPACKETSIZE];
    int  bytesSent;


    if(fdShare((SOCKET)clientfd)){
    	System_printf("share failed\n");
    	System_flush();
    }


    Mbdata_t mbData = {.code = 7};
    while ((bytesRcvd = recv(clientfd, buffer, TCPPACKETSIZE, 0)) > 0) {

    	/*
    	bytesSent = send(clientfd, buffer, TCPPACKETSIZE, 0);
    	if (bytesSent < 0 || bytesSent != TCPPACKETSIZE) {
			System_printf("Error: send failed: %d.\n",bytesSent);
			System_flush();
			break;
		}
		*/
    	memcpy(mbData.buff,buffer,TCPPACKETSIZE);
    	Mailbox_post(transmitMb,&mbData,BIOS_WAIT_FOREVER);

	}

    mbData.code = 6;
    Mailbox_post(transmitMb,&mbData,BIOS_WAIT_FOREVER);


    if(fdClose((SOCKET)clientfd)){
    	System_printf("fdClose failed\n");
    	System_flush();
    }



}

Void tcptransmit(UArg arg0, UArg arg1)
{
    int  clientfd = (int)arg0;
    int  bytesSent;
    Mbdata_t mbData;


    if(fdShare((SOCKET)clientfd)){
       	System_printf("share failed\n");
       	System_flush();
       }


    while(1){

    	Mailbox_pend(transmitMb,&mbData,BIOS_WAIT_FOREVER);

    	if(mbData.code == 6)
    		break;
    	else{

    		bytesSent = send(clientfd, mbData.buff, TCPPACKETSIZE, 0);

    		if (bytesSent < 0 || bytesSent != TCPPACKETSIZE) {
				System_printf("Error: send failed: %d.\n",bytesSent);
				System_flush();
				break;
			}

    	}
    }

    if(fdClose((SOCKET)clientfd)){
       	System_printf("fdClose failed\n");
       	System_flush();
       }


    System_printf("transmit ended\n");
    System_flush();

}

/*
 *  ======== tcpHandler ========
 *  Creates new Task to handle new TCP connections.
 */
Void tcpHandler(UArg arg0, UArg arg1)
{
    int                status;
    int                clientfd;
    int                server;
    struct sockaddr_in localAddr;
    struct sockaddr_in clientAddr;
    int                optval;
    int                optlen = sizeof(optval);
    socklen_t          addrlen = sizeof(clientAddr);
    Task_Handle        taskHandle;
    Task_Params        taskParams;
    Error_Block        eb;

    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server == -1) {
        System_printf("Error: socket not created.\n");
        goto shutdown;
    }


    memset(&localAddr, 0, sizeof(localAddr));
    localAddr.sin_family = AF_INET;
    localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    localAddr.sin_port = htons(arg0);

    status = bind(server, (struct sockaddr *)&localAddr, sizeof(localAddr));
    if (status == -1) {
        System_printf("Error: bind failed.\n");
        goto shutdown;
    }

    status = listen(server, NUMTCPWORKERS);
    if (status == -1) {
        System_printf("Error: listen failed.\n");
        goto shutdown;
    }

    optval = 1;
    if (setsockopt(server, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
        System_printf("Error: setsockopt failed\n");
        goto shutdown;
    }

/*
    struct timeval tv;
    tv.tv_sec = 3;
    tv.tv_usec = 0;
	if (setsockopt(server, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
		System_printf("Error: setsockopt failed\n");
		goto shutdown;
	}
*/

    while ((clientfd = accept(server, (struct sockaddr *)&clientAddr, &addrlen)) != -1) {

        //System_printf("tcpHandler: Creating thread clientfd = %d\n", clientfd);

        /* Init the Error_Block */
        Error_init(&eb);

        /* Initialize the defaults and set the parameters. */
        Task_Params_init(&taskParams);
        taskParams.arg0 = (UArg)clientfd;
        taskParams.stackSize = 2048;
        taskHandle = Task_create((Task_FuncPtr)tcpWorker, &taskParams, &eb);
        if (taskHandle == NULL) {
            System_printf("Error: Failed to create new Task\n");
            close(clientfd);
        }

        Task_Params_init(&taskParams);
		taskParams.arg0 = (UArg)clientfd;
        taskParams.stackSize = 2048;
        taskHandle = Task_create((Task_FuncPtr)tcptransmit, &taskParams, &eb);
		if (taskHandle == NULL) {
			System_printf("Error: Failed to create new Task\n");
			close(clientfd);
		}


        /* addrlen is a value-result param, must reset for next accept call */
        addrlen = sizeof(clientAddr);
    }

    System_printf("Error: accept failed.\n");
    System_flush();

shutdown:
    if (server > 0) {
        close(server);
    }
}

/*
 *  ======== main ========
 */
int main(void)
{
    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();
    Board_initEMAC();

    System_printf("Starting the TCP Echo example\nSystem provider is set to "
                  "SysMin. Halt the target to view any SysMin contents in"
                  " ROV.\n");
    /* SysMin will only print to the console when you call flush or exit */
    System_flush();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

6406.tcpEcho_mod.zip 

  • Hi Daniel,

    I think there may be two problems:
    1. You have one too many fdShare() calls
    2. If a transmit fails, your worker task will remain since it will try to post to the Mailbox forever.

    For 1., each time you call fdShare(), it increases an internal variable that keeps track of how many times it has been opened. In your test case, it would be 3: one from the accept in tcpHandler, one from the tcptransmit, and one from the tcpworker. fdClose() is only called twice: one by the tcptransmit and one by tcpworker. So, clientfd is never properly closed since the program thinks it is still being used and thus lost when you accept a new connection. One way to fix this is to remove one of the fdShare() calls like the one from the tcptransmit.

    For 2., you can fix it by adding a timeout instead of waiting forever. The timeout is based on clock ticks, so if you want a 10s timeout, it would be (10 * 1000) since your current configuration is set for 1000us or ~1ms.

    Regards,
    Gilbert
  • There was a suggested answer and since there has been no active on this thread for more than a week, the suggested answer was marked as verify. Please feel free to select the "Reject Answer" button and reply with more details.
  • Hello,
    Gilbert answer was marked as answer. I think :)