From: Joseph M. Newcomer on
The phrase "was opened by the interpreter" is suggestive of the problem. You must not
create any child window in a thread where the parent was created from another thread. If a
thread needs a window to be created, it should PostMessage a request to the main GUI
thread to create the window, and access that window solely and exclusively by using
PostMessage calls to send messages to that window from the thread. What you appear to have
is classic deadlock, and the only solution is redesign.
joe

On Sun, 10 Jul 2005 11:27:58 +0200, TX <tx(a)tx> wrote:

>Scott McPhillips [MVP] wrote:
>> TX wrote:
>>
>>> I have a problem with blocking of main thread:
>>>
>>> My application contains an interpreter and I need to write a debugger
>>> for it.
>>>
>>> The mainframe creates a thread that is interpreting instructions. When
>>> I need to break execution of instruction thread, I use
>>> WaitForSingleObject(m_WaitEventHandle, INFINITE);
>>> in the interpreter thread.
>>>
>>> Everything works fine until the window is opened from the interpreter.
>>> Then the mainframe freezes.
>>>
>>> When I break execution in VC the call stack for interpreter thread shows:
>>>
>>> ý NTDLL!
>>> ý KERNEL32!
>>> ý CDebugManager::CheckBreakpoints()
>>> ý CInterpreterThread::Run()
>>> ý _AfxThreadEntry()
>>> ý _threadstartex()
>>> ý KERNEL32!
>>>
>>> call stack for the mainframe:
>>> ý CWinThread::Run()
>>> ý CWinApp::Run()
>>> ý AfxWinMain()
>>> ý WinMain()
>>> ý WinMainCRTStartup()
>>> ý KERNEL32!
>>>
>>>
>>> The window opened from interpreter is descendant of CDialog and is
>>> created by calling CDialog::Create(IDD_DIALOG_BASE)
>>>
>>> What can be wrong?
>>> Is it a way to find out why the main thread is blocking?
>>>
>>> Thanks for any help.
>>
>>
>> The main call stack does not look frozen: CWinThread::Run is the main
>> message pump. Assuming that you have installed the MFC source files, a
>> double-click on the top line of the stack will show you where the main
>> thread is executing.
>>
>> Does your main thread attempt to access the dialog or dialog controls
>> created in the second thread? That would cause a deadlock if the second
>> thread is in WaitForSingleObject. The second thread cannot maintain a
>> window while it is in WaitForSingleObject. It is best to put all
>> windows in the main thread.
>>
>
>Now I break execution again and the call stack for main thread shows this:
>
>------------------------
>ý USER32! 77e1392f()
>ý USER32! 77e15709()
>ý CFrameWnd::NotifyFloatingWindows()
>ý CFrameWnd::OnActivate()
>ý CWnd::OnWndMsg()
>ý CWnd::WindowProc()
>ý AfxCallWndProc()
>ý AfxWndProc()
>ý AfxWndProcBase()
>ý USER32! 77e12e98()
>ý USER32! 77e139a3()
>ý USER32! 77e1395f()
>ý NTDLL! 77fa032f()
>ý CWinThread::PumpMessage()
>ý CWinThread::Run()
>ý CWinApp::Run()
>ý AfxWinMain()
>ý WinMain()
>ý WinMainCRTStartup()
>ý KERNEL32! 77e97d08()
>------------------------
>
>When I double-click on CFrameWnd::NotifyFloatingWindows(), the source of
>WinFrm.cpp shows the line marked with =====>
>
>
>------------------------
>void CFrameWnd::NotifyFloatingWindows(DWORD dwFlags)
>{
> ASSERT_VALID(this);
> ASSERT(m_hWnd != NULL);
>
> // get top level parent frame window first unless this is a child window
> CFrameWnd* pParent = (GetStyle() & WS_CHILD) ? this : GetTopLevelFrame();
> ASSERT(pParent != NULL);
> if (dwFlags & (FS_DEACTIVATE|FS_ACTIVATE))
> {
> // update parent window activation state
> BOOL bActivate = !(dwFlags & FS_DEACTIVATE);
> BOOL bEnabled = pParent->IsWindowEnabled();
>
> if (bActivate && bEnabled && pParent != this)
> {
> // Excel will try to Activate itself when it receives a
> // WM_NCACTIVATE so we need to keep it from doing that here.
> m_nFlags |= WF_KEEPMINIACTIVE;
> pParent->SendMessage(WM_NCACTIVATE, TRUE);
> m_nFlags &= ~WF_KEEPMINIACTIVE;
> }
> else
> {
> pParent->SendMessage(WM_NCACTIVATE, FALSE);
> }
> }
>
> // then update the state of all floating windows owned by the parent
> HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
> while (hWnd != NULL)
> {
> if (AfxIsDescendant(pParent->m_hWnd, hWnd))
> ::SendMessage(hWnd, WM_FLOATSTATUS, dwFlags, 0);
>=====> hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
> }
>}
>------------------------
>
>In hWnd is the handle of the window that was opened from the interpreter...

Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm