Handle Leak Source Tracking in WinSock MFC

We are developing an application in which we use the WinSock-based Sime socket approach to communicate with an external module. Our requirement is to ensure that the connection is always on, so for this reason we constantly try to connect every 1 minute when we disconnect.

Our problem begins here. We observed that each time the socket is reconnected, it flows with exactly two Windows descriptors. We tried so many options, but none of them work. What pens can leak and how can we identify the culprit?

Below is the code we are using right now:

bool CSocketClass::ConnectToServer(int nLineNo) { string strIPAddress; int nPortNo; SOCKET* l_ClientSocket; int ConnectionResult; //---------------------- // Create a SOCKET for connecting to server if (nLineNo == 1) { m_objLine1.m_ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); strIPAddress = m_objLine1.m_strIPAddress; nPortNo = m_objLine1.m_nPortNo; l_ClientSocket = &(m_objLine1.m_ClientSocket); } else { m_objLine2.m_ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); strIPAddress = m_objLine2.m_strIPAddress; nPortNo = m_objLine2.m_nPortNo; l_ClientSocket = &(m_objLine2.m_ClientSocket); } if(INVALID_SOCKET == *l_ClientSocket) { return false; } //---------------------- // The sockaddr_in structure specifies the address family, // IP address, and port of the server to be connected to. sockaddr_in clientService; clientService.sin_family = AF_INET; clientService.sin_addr.s_addr = inet_addr( strIPAddress.c_str() ); clientService.sin_port = htons( nPortNo ); //---------------------- // Connect to server. ConnectionResult = connect( *l_ClientSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) ; if (ConnectionResult == SOCKET_ERROR) { if (nLineNo == 1) { //ERROR in line1 } else { //ERROR in line2 } return false; } else //In case of successful connection { //Other actions } return true; } 
+4
source share
5 answers

Try the free Process Explorer from Microsoft. It will display all open process descriptors along with information such as name (for files, mutexes, events, etc.). It will also highlight the newly created and closed pens, so if you go through the cycle cycle and refresh the display, you will see the exact pens that were skipped.

+3
source

Let's say you got the socket correctly:

 m_objLine1.m_ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) m_objLine1.m_ClientSocket != INVALID_SOCKET // true 

but then you cannot connect, therefore

 ConnectionResult = connect( *l_ClientSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) ConnectionResult == SOCKET_ERROR // true 

in this case, you must close this acquired socket descriptor:

 closesocket(m_objLine1.m_ClientSocket); 

You have two lines, so I assume that you call this function twice, once for each line, so why two leaked handles.

+1
source

I suggest you try the Intel Parallel Inspector to identify memory leaks and where they occur.

There is a trial download if you want to try.

0
source

An easy way to find descriptor leaks is to record everything.

Each time you receive a descriptor, register it as you received it, as well as any other information about the circumstances. Each time you release a handle, register that you released it. Include both times the actual descriptor (only one hex).

Then you will get a log that looks like this (for example):

 Obtained handle 0xf000 (nLineNo = 5) Obtained handle 0xb000 (nLineNo = 6) Obtained handle 0xd0d0 (nLineNo = 7) Released handle 0xf000 Released handle 0xb000 

If you select this manually, you will see that you received the 0xd0d0 handle when nLineNo was 7 and it was never released. It is not so much, but it helps, and if the situation becomes tough, you can even try to record stack traces in each receive / release. In addition, if the log is always reliably created in this way, you can start entering breakpoints based on the actual values ​​(for example, a break at a point in the program when the handle is 0xd0d0 so you can see what happens to it).

If this is more practical, you can start wrapping your pens inside the program itself, for example. a std::set all the pens received, as well as any details about when they were received, and you can effectively hack your program to keep track of what it is doing (then undo all your changes after fixing).

Hope this helps - this is part of the reason why I at least keep the std::set everything I get, so if the worst comes to the worst, you can iterate over them when turned off and release them all (and write big "FIX THIS!"!)

0
source

Try adding shutdown(SD_BOTH) to socket descriptors after closesocket(); . Also try adding Sleep for about 100ms (for test only) and see how this happens.

0
source

Source: https://habr.com/ru/post/1348084/


All Articles