none
IcmpSendEcho memory leak on Wec2013 RRS feed

  • Question

  • Hello

    I have a memory leak problem with WEC2013 and IcmpSendEcho

    I have a thread that contnuously invokes this function

    INT Ping(ULONG ulAddr)
    {
       DWORD dwRetVal = 0;
       DWORD dwLastErr = 0;
       //HANDLE hIcmpFile = IcmpCreateFile();
       char szSendData[4] = {'P','I','N','G'};
       char szReplyBuffer[sizeof(szSendData) + sizeof(ICMP_ECHO_REPLY)];
       UCHAR ucOptionsData = 0;
       IP_OPTION_INFORMATION stIPInformation = {254,0,0,sizeof(ucOptionsData),&ucOptionsData};
    
       // Do the ping
       dwRetVal = IcmpSendEcho(hIcmpFile, ulAddr, (LPVOID)szSendData, sizeof(szSendData), &stIPInformation, szReplyBuffer, sizeof(szReplyBuffer), 500);
       if (dwRetVal)
       {
          // if succeeded -> return round trip time
          ICMP_ECHO_REPLY* pReply = (ICMP_ECHO_REPLY*)szReplyBuffer;
          dwRetVal = pReply->RoundTripTime;
       }
       else
       {
          dwRetVal = SOCKET_ERROR;
       }
    
       //IcmpCloseHandle(hIcmpFile);
    
       return dwRetVal;
    }
    

    here is the thread function

    DWORD PingThread(LPVOID lpEntryArgs)
    {
    ULONG ulAddr = htonl(inet_addr(PINGPARTNER));
    PingInit();
    
    while(bRun)
    {
    /*
    DWORD dwRet = Ping(ulAddr);
    DWORD dwLastErr = 0;
    if (dwRet == 0)
    {
    dwLastErr = GetLastError();
    }
    */
    Sleep(2);
    }
    PingDeinit();
    return 0;
    }


    If I comment out the call to the Ping function (which invokes IcmpSendEcho) I see that memory used do not increase for days. But if I invoke the Ping function, the memory used starts growing until the device resets due to lack of resources.

    Note that the test application includes also calls to other network-related functions (sendto, recvfrom), but they seem not to be responsible for the memory leak. Am I correct or is there some interactions between sockets and IcmpSendEcho?

    Is there any fix or workaround for this?

    Thanks in advance



    Tuesday, July 19, 2016 9:17 AM

All replies

  • Is hIcmpFile a global variable somewhere? Show us all the relevant code (in a code formatted block preferably) so we can help you better.

    Good luck,

    Michel Verhagen, eMVP
    Check out my blog: https://guruce.com/blog

    GuruCE
    Microsoft Embedded Partner
    NXP Proven Partner
    https://guruce.com
    Consultancy, training and development services.

    Interested in WEC on i.MX6?
    Get the only 100% stable and best performing i.MX6 BSP for WEC7 and WEC2013 here: https://guruce.com/imx6

    Tuesday, July 19, 2016 11:55 AM
    Moderator
  • Hi Almgabu,

    I agree with Michel's suggestion as we don't have the whole picture here.  You should be looking for allocations that you are not freeing in your calls. If you step through the loop with the debugger, can you identify the source of the allocation without a corresponding free?

    Sincerely,

    IoTGirl

    Tuesday, July 19, 2016 5:00 PM
    Moderator
  • Hi

    yes, hIcmpFile is a global variable. it is initialized in the PingInit function. This function is very simple:

    void PingInit()
    {
      hIcmpFile = IcmpCreateFile();
    }


    Thursday, July 21, 2016 6:46 AM
  • Don't know how to make my statements more clear, but I will try

    DWORD PingThread(LPVOID lpEntryArgs) { ULONG ulAddr = htonl(inet_addr(PINGPARTNER)); PingInit(); while(bRun) { /* DWORD dwRet = Ping(ulAddr); DWORD dwLastErr = 0; if (dwRet == 0) { dwLastErr = GetLastError(); } */ Sleep(2); }

    PingDeinit(); return 0; }

    When I comment this line 

    DWORD dwRet = Ping(ulAddr);

    I DO NOT see the memory leak.

    When I include the above-mentioned line, I see a memory leak. The Ping function is in the original post, but let's paste it again for the sale of completeness

    INT Ping(ULONG ulAddr) { DWORD dwRetVal = 0; DWORD dwLastErr = 0; //HANDLE hIcmpFile = IcmpCreateFile(); char szSendData[4] = {'P','I','N','G'}; char szReplyBuffer[sizeof(szSendData) + sizeof(ICMP_ECHO_REPLY)]; UCHAR ucOptionsData = 0; IP_OPTION_INFORMATION stIPInformation = {254,0,0,sizeof(ucOptionsData),&ucOptionsData}; // Do the ping dwRetVal = IcmpSendEcho(hIcmpFile, ulAddr, (LPVOID)szSendData, sizeof(szSendData), &stIPInformation, szReplyBuffer, sizeof(szReplyBuffer), 500); if (dwRetVal) { // if succeeded -> return round trip time ICMP_ECHO_REPLY* pReply = (ICMP_ECHO_REPLY*)szReplyBuffer; dwRetVal = pReply->RoundTripTime; } else { dwRetVal = SOCKET_ERROR; } //IcmpCloseHandle(hIcmpFile); return dwRetVal; }

    As you can see, there is no new,malloc or any other form of dynamic memory allocation.

    And the only function here is IcmpSendEcho, which source code is not provided.
    As you can see I also removed the call to the IcmpCreateFile from the Ping function, and moved it in another function (PingInit) which is called just once when thread starts up


    • Edited by amgalbu Thursday, July 21, 2016 6:55 AM
    Thursday, July 21, 2016 6:52 AM
  • Can you try adding another 8 bytes to the szReplyBuffer?

    The info on the IcmpSendEcho page says:

    This buffer should also be large enough to also hold 8 more bytes of data (the size of an ICMP error message).


    Good luck,

    Michel Verhagen, eMVP
    Check out my blog: https://guruce.com/blog

    GuruCE
    Microsoft Embedded Partner
    NXP Proven Partner
    https://guruce.com
    Consultancy, training and development services.

    Interested in WEC on i.MX6?
    Get the only 100% stable and best performing i.MX6 BSP for WEC7 and WEC2013 here: https://guruce.com/imx6

    • Marked as answer by amgalbu Wednesday, August 24, 2016 10:38 AM
    • Unmarked as answer by amgalbu Friday, September 9, 2016 2:13 PM
    Thursday, July 21, 2016 7:15 AM
    Moderator
  • Thanks Michel

    I will make more tests, but it seems that was the problem

    Best regards

    Wednesday, August 24, 2016 10:39 AM
  • Unfortunately the issue seems to be still there...

    Any other suggestion?

    Thanks in advance


    Friday, September 9, 2016 2:12 PM
  • So it seemed to fix the problem for two weeks (the time between when you said "it's fixed" and "it's not fixed")?

    In any case, capturing the debug output messages, particularly from the network stack, from a DEBUG build of the operating system is a good place to start. You say that your thread "continuously" invokes Ping(). How frequently (2ms)? I'm sure that the programmers at Microsoft didn't expect the ICMP protocol to be invoked every 2ms for the life of a device. Maybe there's a queue issue or a buffer issue that causes some handles to be lost. If you increase the cycle time of Ping() from 2ms to 50ms, do you still get a leak, but at 1/25 the rate or does the leak disappear?

    On the assumption that the leak is real and a bug in the operating system, what are you trying to achieve with continuous ICMP activity? Tell us a bit about the networking context you're working in and why you chose ICMP, rather than, for example, TCP connection directly to the target system and monitoring the health of that connection with keep-alive or something. If you just want to make sure the local device is still on the network, there are better ways using NDIS calls to check the health of the Ethernet or WiFi connection itself, rather than checking round-trip time across the network.

    Paul T.

    Friday, September 9, 2016 5:04 PM