We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Can't find a memory leak

Argonaut
Argonaut asked
on
Medium Priority
418 Views
Last Modified: 2013-11-20
I have a windows service that has a nagging memory leak.  I am not the code author so there are things I don't understand yet.  If I watch memory usage in task manager I see the available memory slowly decrease as my process usage increases.  My process then seems to release the memory but the system available never reclaims it.  Eventually all memory is used.  I found that the use of CreateThread is not recommended so I tried beginthreadex but that did not help.  I'm thinking that maybe a thread is not completeing successfully and then not being released.  But since I'm not really a C++ or threading expert I'm not sure what to do.  Here is the main cpp file, I can post others if required.


void CAISController::Start()
{
      long lCount = 0;
      long lVal = 0;
      long lReasonCode = 0;
      CString csMsgID;
      CString csRequest;
      CString csReply;
      CString csErrorMsg;
      CQueueManager objQueueManager;
      HANDLE hThreadHandle;
      HANDLE hReplyThreadHandle;
      DWORD dwThreadID = 0;
      DWORD dwSuspendCount = 0;
      DWORD dwExitCode = 0;
      tagReplyStruct* pReplyStruct = NULL;
      tagRequestStruct* pRequestStruct = NULL;
      int nIndex = 0;
      int nReplyIndex = 0;
      int nConnIndex = 0;
      int nCount = 0;
      CPtrArray colReplyStructHandles;
      CPtrArray colStaticConnectPoolHandles;
      void* pContext = NULL;
      CStaticConnectionPool* pobjStaticConnectionPool = NULL;
      CTiming* pobjTiming = NULL;
      MSG msg;
      
      // initializes cae for multi-threaded static sql
      sqleSetTypeCtx(SQL_CTX_MULTI_MANUAL);

      try
      {
            // create max request thread semaphore to limit the total request threads
            g_hMaxRequestThreadSemaphore = CreateSemaphore(NULL,
                                                                                 g_objApp->GetAppThreadMax(),
                                                                                 g_objApp->GetAppThreadMax(),NULL);

            // create max database connection semaphore to limit the total connections
            g_hMaxConnectionSemaphore = CreateSemaphore(NULL,  // no security attributes
                                                                              g_objApp->GetDBMaxConnections(),
                                                                              g_objApp->GetDBMaxConnections(),
                                                                              NULL);  // unnamed semaphore


            //call the CodeText Build
            g_objCodeText.Build();
            if (g_objErrorLog->HasError())
            {
                  // System error logged during build
                  // Log a page error to notify support and shutdown
                  g_bShutDown = true;
                  csErrorMsg = _T("A severe error was encountered during service start.");
                  csErrorMsg += _T(" The service will now shutdown.");
                  g_objErrorLog->Add(0, _T("AISController::Start()"),
                        csErrorMsg, CErrorLog::SYSTEM_EMAIL_PAGE);
            }

            objQueueManager.ConnectQueueManager();
            if (g_objErrorLog->HighestSeverity() < CErrorLog::SYSTEM_EMAIL_PAGE)
            {
                  // it's ok to continue if only a "warning" type error occured
                  colStaticConnectPoolHandles.SetSize(g_objApp->GetDBConnectionPools());
                  nCount = colStaticConnectPoolHandles.GetSize();

                  for(nIndex = 0; nIndex < nCount; nIndex++)
                  {
                        // establish Database connections
                        pobjStaticConnectionPool = new CStaticConnectionPool;
                        pobjStaticConnectionPool->Build(g_objErrorLog);
                        if (g_objErrorLog->HasError())
                        {
                              // System error logged during build
                              // Log a page error to notify support
                              // Shutdown the service
                              g_bShutDown = true;
                              csErrorMsg = _T("A severe error was encountered during service start.");
                              csErrorMsg += _T(" The service will now shutdown.");
                              g_objErrorLog->Add(0, _T("AISController::Start()"),
                                    csErrorMsg, CErrorLog::SYSTEM_EMAIL_PAGE);
                        }
                        colStaticConnectPoolHandles.SetAt(nIndex, pobjStaticConnectionPool);
                  }

                  colReplyStructHandles.SetSize(g_objApp->GetReplyQueueThreads());
                  nCount = colReplyStructHandles.GetSize();

                  for(nIndex = 0; nIndex < nCount; nIndex++)
                  {
                        // create Reply Threads
                        pReplyStruct = new tagReplyStruct;

                        // multi-threaded call
                        hReplyThreadHandle = ::CreateThread(NULL,
                                                                          0,
                                                                          &MultiThreadProcessReply,
                                                                          (LPVOID)pReplyStruct,
                                                                          THREAD_PRIORITY_NORMAL,
                                                                          &dwThreadID);

                        colReplyStructHandles.SetAt(nIndex, pReplyStruct);
                  }

                  nReplyIndex = 0;
                  nConnIndex = 0;
            }

            while (g_bShutDown != true)
            {

                  if (pRequestStruct == NULL)
                        pRequestStruct = new tagRequestStruct;                  
                  
                  pRequestStruct->csMessage = objQueueManager.GetRequestMessage(&pRequestStruct->cMsgID[0]);

                  pRequestStruct->pobjTiming->Checkpoint(CTiming::AIS_CONTROLLER);

                  if (pRequestStruct->csMessage != "" && g_objErrorLog->HighestSeverity() < CErrorLog::SYSTEM_EMAIL_PAGE)
                  {
                        //thread should go to sleep if all request threads are in use
                        WaitForSingleObject(g_hMaxRequestThreadSemaphore, INFINITE);  // no timeout period

                        if (nReplyIndex > (colReplyStructHandles.GetSize() - 1))
                              nReplyIndex = 0;
                        
                        pRequestStruct->pReplyStruct = (tagReplyStruct*)colReplyStructHandles.GetAt(nReplyIndex);

                        if (nConnIndex > (colStaticConnectPoolHandles.GetSize() - 1))
                              nConnIndex = 0;
                        
                        pRequestStruct->pobjStaticConnectionPool = (CStaticConnectionPool*)colStaticConnectPoolHandles.GetAt(nConnIndex);

                        // spawn the Request Thread
                        hThreadHandle = ::CreateThread(NULL,
                                                           0,
                                                                     &MultiThreadProcessRequest,
                                                                     (LPVOID)pRequestStruct,
                                                                     THREAD_PRIORITY_NORMAL,
                                                                     &dwThreadID);

                        ::CloseHandle(hThreadHandle);

                        nReplyIndex++;
                        nConnIndex++;
                        pRequestStruct = NULL;
                  }
                  // check to make sure that there are no messages
                  if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE) != 0)
                  {
                        // if it is a quit message then set the global
                        // variable to true
                        if (msg.message == WM_QUIT)
                              g_bShutDown = true;
                        DispatchMessage(&msg);
                        
                  }
            }
            
            if (pRequestStruct != NULL)
                  delete pRequestStruct;
 
            objQueueManager.DisconnectQueueManager();

            nCount = colReplyStructHandles.GetSize();


            // wake up each thread so it can kill itself and exit normally
            for(nIndex = 0; nIndex < nCount; nIndex++)
            {
                  pReplyStruct = (tagReplyStruct*)colReplyStructHandles.GetAt(nIndex);
                  // Now that the thread has to die or rather commit sucide, set the event to signaled
                  ::SetEvent(pReplyStruct->hDataAvailableEvent);
            }

            // now wait a couple of seconds until all threads are complete
            ::Sleep(5000);

            // get rid of Reply structures
            for(nIndex = 0; nIndex < nCount; nIndex++)
            {
                  pReplyStruct = (tagReplyStruct*)colReplyStructHandles.GetAt(nIndex);
                  if (pReplyStruct !=NULL)
                        delete pReplyStruct;
            }

            colReplyStructHandles.RemoveAll();

            // delete Static Connections
            nCount = colStaticConnectPoolHandles.GetSize();
            for (nIndex=0; nIndex < nCount; nIndex++)
            {
                  pobjStaticConnectionPool = (CStaticConnectionPool*)colStaticConnectPoolHandles.GetAt(nIndex);
                  pobjStaticConnectionPool->Destroy(g_objErrorLog);
                  delete pobjStaticConnectionPool;
            }

            colStaticConnectPoolHandles.RemoveAll();

            g_objCodeText.Destroy();

      }
      catch(...)
      {
            TRACE("\nCaught Exception in AISController::Start()\n");      
            g_objErrorLog->Add(GetLastError(), _T("AISController::Start"),
                  _T("Unknown Exception Caught"), CErrorLog::SYSTEM_WARNING);
      }

}
Comment
Watch Question

Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
CERTIFIED EXPERT
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.