pNacl memory leak in simple UDP test program

246 views
Skip to first unread message

Dongyang Zhang

unread,
Aug 11, 2014, 6:42:59 PM8/11/14
to native-cli...@googlegroups.com
Hi there,

I am seeing memory leak in our pNacl application on various OS. The UDP test program below is sending 1MB data per second from the server to client; it emulates our app's UDP communication; I am using this test to narrow down the module that causes memory leak:

Memory keeps growing when the test runs on the same machine with server and client in two threads.

There must be memory leak in nacl libs. Can someone help fix it? We are blocked by this memory leak issue in our current project. Any help would be appreciated!

Thanks!
Dongyang

void SocketTestInstance::startClient( int32_t cresult )
{
    //create a socket and connect.
    int sock;                        /* Socket descriptor */
    struct sockaddr_in echoServAddr, echoClientAddr; /* Echo server address */
    const char *servIP = "127.0.0.1";                    /* Server IP address (dotted quad) */
    const char *echoString = "something";                /* String to send to echo server */
    char echoBuffer[RCVBUFSIZE];     /* Buffer for echo string */
    unsigned int echoStringLen;      /* Length of string to echo */
    unsigned long bytesRcvd, totalBytesRcvd, bytesSent;   /* Bytes read in single recv()
                                    and total bytes read */
    LOG_INFO(" Start Client!\n" );

    if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
        LOG_INFO("socket() failed\n");
        return;
    }
    LOG_INFO("client: socket() success\n");

    memset(&echoClientAddr, 0, sizeof(echoClientAddr));     /* Zero out structure */
    echoClientAddr.sin_family      = AF_INET;             /* Internet address family */
    echoClientAddr.sin_addr.s_addr = inet_addr(servIP);   /* Server IP address */
    echoClientAddr.sin_port        = htons(7777); /* Server port */

    /* Bind to the local address */
    if (bind(sock, (struct sockaddr *) &echoClientAddr, sizeof(echoClientAddr)) < 0)
        DieWithError("client bind() failed\n");

    long size = 1024 * 1024;
    int status = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (const char *)&size, sizeof(size));
    if (-1 == status)
    {
        DieWithError("client setsockopt() failed\n");
    }
        
    LOG_INFO("Client: bind() success\n");

    /* Construct the server address structure */
    memset(&echoServAddr, 0, sizeof(echoServAddr));     /* Zero out structure */
    echoServAddr.sin_family      = AF_INET;             /* Internet address family */
    echoServAddr.sin_addr.s_addr = inet_addr(servIP);   /* Server IP address */
    echoServAddr.sin_port        = htons(5555); /* Server port */
    
    echoStringLen = strlen(echoString);          /* Determine input length */

    /* Send the string to the server */
    bytesSent = sendto(sock, echoString, echoStringLen, 0, (struct sockaddr*)&echoServAddr, sizeof(echoServAddr));
    LOG_INFO("client: sent: %lu \n", bytesSent);        

    totalBytesRcvd = 0;
    while (1)
    {
        socklen_t addrlen = sizeof(echoServAddr);
        bytesRcvd = recvfrom(sock, echoBuffer, RCVBUFSIZE, 0, (struct sockaddr*)&echoServAddr, &addrlen);
        totalBytesRcvd += bytesRcvd;   /* Keep tally of total bytes */
        static int count = 0;
        if (0 == count++ % 100) {
            LOG_INFO("client received %lu bytes\n", totalBytesRcvd);      /* Print the echo buffer */    
        }
    }

    LOG_INFO("\n");    /* Print a final linefeed */

    close(sock);


}

void SocketTestInstance::startServer( int32_t cresult )
{
    int servSock;                    /* Socket descriptor for server */
    struct sockaddr_in echoServAddr; /* Local address */
    struct sockaddr_in echoClntAddr; /* Client address */
    char echoBuffer[RCVBUFSIZE];        /* Buffer for echo string */
    static unsigned char dataToSend[RCVBUFSIZE]={42};
    unsigned long bytesRcvd, bytesSent, totalBytesRcvd = 0;   /* Bytes read in single recv()*/


    LOG_INFO("Server: started\n");
    /* Create socket for incoming connections */
    if ((servSock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
        DieWithError("socket() failed\n");
    LOG_INFO("Server: socket() success\n");
    /* Construct local address structure */
    memset(&echoServAddr, 0, sizeof(echoServAddr));   /* Zero out structure */
    echoServAddr.sin_family = AF_INET;                /* Internet address family */
    echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
    echoServAddr.sin_port = htons(5555);      /* Local port */

    /* Bind to the local address */
    if (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
        DieWithError("server bind() failed\n");

    LOG_INFO("Server: bind() success\n");

    /* Mark the socket so it will listen for incoming connections */
    sleep(2);
    socklen_t addrlen = sizeof(echoClntAddr);
    bytesRcvd = recvfrom(servSock, echoBuffer, RCVBUFSIZE, 0, (struct sockaddr*)&echoClntAddr, &addrlen);
    LOG_INFO("Server bytesReceived: %lu\n", bytesRcvd);

    for (;;) /* Run forever */
    {
        bytesSent = sendto(servSock, dataToSend, RCVBUFSIZE, 0, (struct sockaddr*)&echoClntAddr, sizeof(echoClntAddr));
        usleep(10000);

        totalBytesRcvd += bytesSent;
        static int count = 0; 
        if (0 == count++ % 100) {
            LOG_INFO("server sent: %lu bytes\n", totalBytesRcvd);      /* Print the echo buffer */    
        }
    }
    /* NOT REACHED */

    close(servSock);    /* Close client socket */
}

Sam Clegg

unread,
Aug 19, 2014, 6:02:14 AM8/19/14
to native-cli...@googlegroups.com
Hi Dongyang,

I'm happy to take a look at tracking down the leak, but it would help
a lot if you could supply a full test program. (using ppapi_simple
would be the easiest way to do this).

cheers,
sam
> --
> You received this message because you are subscribed to the Google Groups
> "Native-Client-Discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to native-client-di...@googlegroups.com.
> To post to this group, send email to native-cli...@googlegroups.com.
> Visit this group at http://groups.google.com/group/native-client-discuss.
> For more options, visit https://groups.google.com/d/optout.

Ben Smith

unread,
Aug 19, 2014, 2:24:53 PM8/19/14
to native-cli...@googlegroups.com
I was able to repro this bug. I have a CL with a fix here: https://codereview.chromium.org/487363003/
> email to native-client-discuss+unsub...@googlegroups.com.

Dongyang Zhang

unread,
Aug 19, 2014, 5:39:38 PM8/19/14
to native-cli...@googlegroups.com
Thanks Sam and Ben for the reply!

Ben,

I tested your change it works on linux and fixed the leak. But on windows it still shows memory leak but it grows at a much slower rate (2kB/sec sometime it drops and goes on increasing);

Sam,

I attached the zip of the udp test app package. Source code is packaged as well. When I built it, it linked against the libnacl_io.a with Ben's fix. So on linux it works fine but on windows it still leaks at a slow growth rate. You may rebuild it with your nacl sdk to repro the leak.
udptest_mem_leak_fix.zip
Reply all
Reply to author
Forward
0 new messages