Why win32 thread does not exit automatically?

Background:

In my C ++ application, I create a work thread, which in turn creates two threads using CreateThread() . The two threads that the workflow creates communicate with the WCF service through a client, which is implemented using the Windows Web Services API , which offers C / C ++ programming interface (API) for creating SOAP-based web services and clients. My application only implements a client using this API.

Problem:

The problem I am facing is that all other threads are exiting gracefully, with the exception of the worker thread, as you can see in the image below, that WorkerThreadProc does not use CPU cycles, but does not exit. There are also several other threads that are not created by me, but at runtime.

The state of the stream is as follows (as ProcessExplorer reports):

  • WorkerThreadProc is in a Wait state : WrUserRequest .
  • wWinMainCRTStartup is in a Wait state : UserRequest .
  • All TpCallbackIndependent are in a Wait state : WrQueue .

What are they waiting for? What are the possible reasons why I need to look? Also, what is the difference between WrUserRequest and UserRequest? And what does WrQueue mean? I absolutely do not know what is going on here.

enter image description here


Here is my WorkerThreadProc code. I deleted all registration instructions, except the last one, at the bottom of the function:

 DWORD WINAPI WorkerThreadProc(PVOID pVoid) { //Initialize GDI+ GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; Status status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); if ( status != Status::Ok ) { return 1; } GuiThreadData *pGuiData = (GuiThreadData*)pVoid; auto patternIdRequestQueue= new PatternIdRequestQueue(); auto resultQueue = new ResultQueue(); auto patternManager = new PatternManager(patternIdRequestQueue); LocalScheduler *pScheduler = new LocalScheduler(resultQueue, patternManager); bool bInitializationDone = pScheduler->Initialize(pGuiData->m_lpCmdLine); if ( !bInitializationDone ) { return 0; } //PatternIdThread PatternIdThread patternIdThread(patternIdRequestQueue); DWORD dwPatternIdThreadId; HANDLE hPatternIdThread = CreateThread(NULL, 0, PatternIdThreadProc, &patternIdThread, 0, &dwPatternIdThreadId); ResultPersistence resultPersistence(resultQueue); DWORD dwResultPersistenceThreadId; HANDLE hResultPersistenceThread = CreateThread(NULL, 0, ResultPersistenceThreadProc, &resultPersistence, 0, &dwResultPersistenceThreadId); pScheduler->ScheduleWork(pGuiData->m_hWnd, pGuiData->m_hInstance, ss.str()); pScheduler->WaitTillDone(); patternIdThread.Close(); resultPersistence.Close(); delete pScheduler; //Uninitialize GDI+ GdiplusShutdown(gdiplusToken); dwRet = WaitForSingleObject(hPatternIdThread, INFINITE); CloseHandle(hPatternIdThread); dwRet = WaitForSingleObject(hResultPersistenceThread,INFINITE); CloseHandle(hResultPersistenceThread); SendMessage(pGuiData->m_hWnd, WM_CLOSE, 0, 0); //IMPORTANT : this verbose message is getting logged! T_VERBOSE(EvtSrcInsightAnalysis, 0, 0, "After sending message to destroy window"); delete patternManager; delete patternIdRequestQueue; delete resultQueue; return 0; } 

See macro T_VERBOSE , it is used to register a detailed message. I see that the message is being logged, but the stream does not exit!


EDIT:

I just commented on the next line in WorkerThreadProc , then the workflow exits gracefully!

 SendMessage(pGuiData->m_hWnd, WM_CLOSE, 0, 0); 

Does this mean that SendMessage is the culprit? Why does it block the thread by the calling thread?

+6
source share
1 answer

If we look at the docs for SendMessage , you can see this little quote:

To send a message and return immediately, use SendMessageCallback or SendNotifyMessage. To send a message to a queue flow and return message immediately, use the PostMessage or PostThreadMessage function.

and this:

Messages sent between threads are processed only when the receiving thread executes the message search code. The sending stream is blocked until the receiving stream processes the message. However, the sending thread will process incoming unreserved messages, waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK. For more information about unregistered messages, see Unexpected Messages.

therefore, from this we can see that SendMessage will block until the message is processed, which may somehow lead to a deadlock in your code, since msgproc is not in the workflow, which leads to a context switch (which only starts when the queue threads downloaded for messages). Try using PostMessage , which returns immediately.

EDIT: there is also a small small piece of information here about message deadlocks from SendMessage

+3
source

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


All Articles