Codejock Forums Homepage
Forum Home Forum Home > Codejock Products > Visual C++ MFC > Docking Pane
  New Posts New Posts RSS Feed - Invalid m_pSelectedPane causes abort
  FAQ FAQ  Forum Search   Events   Register Register  Login Login

Invalid m_pSelectedPane causes abort

 Post Reply Post Reply
Author
Message
rdhd View Drop Down
Senior Member
Senior Member
Avatar

Joined: 13 August 2007
Location: United States
Status: Offline
Points: 605
Post Options Post Options   Thanks (0) Thanks(0)   Quote rdhd Quote  Post ReplyReply Direct Link To This Post Topic: Invalid m_pSelectedPane causes abort
    Posted: 13 April 2015 at 6:19pm
It appears to me that the CXTPDockingPaneTabbedContainer can still have a deleted pane stored in its m_pSelectedPane member data. This leads to a crash when an OnPaint message comes through the tabbed container. Our customers reported this when they take remote control of our application via GoToMeeting.com (or the Siemens AppShare application).

Using trace points I have determined that a CXTPDockingPane is getting deleted while it is still in a tabbed container as the m_pSelectedPane. The tabbed container doesn't get deleted but retains the deleted pointer. This appears to occur when loading layouts and is easiest to duplicate by running GoToMeeting.com and then having a remote user take control of the application and exercising the application remotely in such a way that layouts are saved and loaded.

I can also duplicate this directly by placing breakpoints in various code locations such as the pane and tabbed container ctors, dtors and SelectPane methods.

And lucky for me, I found the CodeJock\Samples\DockingPane\PaneSample and I can duplicate it there. I saved two layouts using the sample to layout1.xml and layout2.xml. Then I took remote control of the sample from my other machine using GoToMeeting.com and started selecting the layout load commands. After a couple of selections, I crashed. The call stack looks like the stacks I have been debugging in our app.

Here is the sample's call stack where I have crashed because the IsTitleVisible method has a non-zero m_pSelectedPane, which is no longer valid (the crash is an AV in GetDockingPaneManager in this case though the exact crash depends on the values in memory):

     ToolkitPro1631vc110x64UD.dll!CXTPDockingPaneBase::GetDockingPaneManager() Line 210    C++
     ToolkitPro1631vc110x64UD.dll!CXTPDockingPane::GetOptions() Line 451    C++
>    ToolkitPro1631vc110x64UD.dll!CXTPDockingPaneTabbedContainer::IsTitleVisible() Line 571    C++
     ToolkitPro1631vc110x64UD.dll!CXTPDockingPaneVisualStudio2012Theme::DrawPane(CDC * pDC, CXTPDockingPaneTabbedContainer * pPane, CRect rc) Line 311    C++
     ToolkitPro1631vc110x64UD.dll!CXTPDockingPaneTabbedContainer::OnPaint() Line 552    C++
     mfc110ud.dll!CWnd::OnWndMsg(unsigned int message, unsigned __int64 wParam, __int64 lParam, __int64 * pResult) Line 2460    C++
     ToolkitPro1631vc110x64UD.dll!CXTPDockingPaneTabbedContainer::OnWndMsg(unsigned int message, unsigned __int64 wParam, __int64 lParam, __int64 * pResult) Line 1485    C++
     mfc110ud.dll!CWnd::WindowProc(unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 2137    C++
     mfc110ud.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 290    C++
     mfc110ud.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 453    C++
     mfc110ud.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 304    C++
     user32.dll!UserCallWinProcCheckWow()    Unknown
     user32.dll!DispatchClientMessage()    Unknown
     user32.dll!__fnDWORD()    Unknown
     ntdll.dll!KiUserCallbackDispatcherContinue()    Unknown
     user32.dll!NtUserCallHwndLock()    Unknown
     mfc110ud.dll!CWnd::UpdateWindow() Line 138    C++
     mfc110ud.dll!CFrameWnd::OnIdleUpdateCmdUI() Line 2154    C++
     mfc110ud.dll!CMDIFrameWnd::OnIdleUpdateCmdUI() Line 248    C++
     mfc110ud.dll!CWnd::OnWndMsg(unsigned int message, unsigned __int64 wParam, __int64 lParam, __int64 * pResult) Line 2460    C++
     ToolkitPro1631vc110x64UD.dll!CXTPCommandBarsSiteBase<CMDIFrameWnd>::OnWndMsg(unsigned int message, unsigned __int64 wParam, __int64 lParam, __int64 * pResult) Line 200    C++
     mfc110ud.dll!CWnd::WindowProc(unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 2137    C++
     mfc110ud.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 290    C++
     mfc110ud.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 453    C++
     mfc110ud.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 304    C++
     user32.dll!UserCallWinProcCheckWow()    Unknown
     user32.dll!CallWindowProcW()    Unknown
     ToolkitPro1631vc110x64UD.dll!CXTPHookManager::HookWndProc(HWND__ * hWnd, unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 267    C++
     user32.dll!UserCallWinProcCheckWow()    Unknown
     user32.dll!DispatchMessageWorker()    Unknown
     mfc110ud.dll!AfxInternalPumpMessage() Line 183    C++
     mfc110ud.dll!CWinThread::PumpMessage() Line 900    C++
     mfc110ud.dll!CWinThread::Run() Line 629    C++
     mfc110ud.dll!CWinApp::Run() Line 780    C++
     mfc110ud.dll!AfxWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 47    C++
     Pane.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 26    C++


We are using 16.3.1 and I have searched the release notes for later releases and see no mention of this issue being resolved.

What I have not figured out is how a call to a pane's destructor is made without the parent container getting another pane selected in its place or the parent container being destroyed too. When I crash, the tabbed container is still valid and it has a valid hWnd (hence the response to WM_PAINT).

Perhaps int the layout code there is a missing reference counting problem on the pane or tabbed container.

Can someone at CodeJock verify this problem and let me know if there is a fix in hand, and if so, what it is so we can determine what we should do? We are about to release so I can't move to a newer toolkit now but I will readily modify the code until we can get a new release.
Back to Top
rdhd View Drop Down
Senior Member
Senior Member
Avatar

Joined: 13 August 2007
Location: United States
Status: Offline
Points: 605
Post Options Post Options   Thanks (0) Thanks(0)   Quote rdhd Quote  Post ReplyReply Direct Link To This Post Posted: 14 April 2015 at 3:56pm
I left out some important information. I see this when running the app on Windows 8.1. I exported my breakpoints and sent them to my Windows 7 box and run the same workflow and I do not crash. I don't crash when switching presenters on GoToMeeting so that I can take control of the app running on my Win7 box from my Win 8.1 box.

Also, debugging the layout code I started breaking in CXTPDockingPaneLayout::Free in the loop over the m_listStack member. There it calls pPane->DeletePane and I can observe that the docking pane that is eventually in the "m_pSelectedPane" of the tabbed container that causes the crash has a ref count of one and hence the call to DeletePane actually causes the pane to delete. I also see the tabbed container in the loop and when DeletePane is called on it, the ref count is 9. Hence the pane isn't really deleted. The window remains and when the frame redisplays the tabbed container gets the WM_PAINT message and then access the deleted m_pSelectedPane pane object (kaboom). I wonder why that code doesn't get the m_pContainer member of the docking pane and call RemovePane to make sure the m_pSelectedPane is changed?

Does CJ even monitor these posts or am I wasting my time debugging their code? Looks like I'll have to open a support case to get a response.
Back to Top
rdhd View Drop Down
Senior Member
Senior Member
Avatar

Joined: 13 August 2007
Location: United States
Status: Offline
Points: 605
Post Options Post Options   Thanks (0) Thanks(0)   Quote rdhd Quote  Post ReplyReply Direct Link To This Post Posted: 14 April 2015 at 5:47pm
I don't recall why but when I first was told of this by a customer I suspected the Windows 8.1 uiautomation.dll and/or combase.dll - probably because on my Win 7 box I don't see combase.dll in the process. Now I am debugging CCmdTarget::ExternalAddRef/Release and I see calls made to the tabbed container. Some calls are for the fact that it is a drop target but those references balance out (observed when the tabbed container calls Register). But then I set a conditional breakpoint for when the ref cnt exceeded 4. I see calls being made for the IAccessible interface. It sure looks like some of those ref counts are not released on Win 8.1. The elevated count causes the tabbed container to not get deleted when the layout calls DeletePane.

I have not determined for sure if it is the MS dll leaking since I can't shut down due to the crash. It seems prudent for CJ to ensure the deleted docking pane is properly disconnected from the tabbed container since the tabbed container doesn't add ref the selected pane it is storing.

I had sent a query to Microsoft regarding those two Dlls an dof course Microsoft denied any knowledge of the DLLs causing issues on Win 8. My combase.dll version is 6.3.9600.17415 and uiautomation version is 7.2.9600.17415.

Debugging the pane sample on my Win 7 box, I don't detect any calls from combase to CCmdTarget::ExternalQueryInterface.

I see that the m_bEnableActiveAccess member is false when the tabbed container's OnGetObject is called.I think I'll remove that handler from the message map and see what happens.
Back to Top
rdhd View Drop Down
Senior Member
Senior Member
Avatar

Joined: 13 August 2007
Location: United States
Status: Offline
Points: 605
Post Options Post Options   Thanks (0) Thanks(0)   Quote rdhd Quote  Post ReplyReply Direct Link To This Post Posted: 14 April 2015 at 6:26pm
Just in case someone is listening ...

I modified the message map for CXTPDockingPaneTabbedContainer by commenting out the handler for WM_GETOBJECT. Now the call is handled by CWnd, which for the tabbed container (at least) has the m_bEnableActiveAccessibility member set to false so that it just calls Default().

Now the CJ docking pane sample runs as expected. I don't see any elevated ref counts on tabbed containers when the layout Free method calls DeletePane.

I asked Microsoft about AccessibleObjectFromWindowTimeout as I see it calls to Release - but not on all the windows. The name makes me wonder if they release the interface in a timely manner. Waiting just a bit to make the call can mean the difference between the Free method of the layout object actually causing the tabbed container to be deleted and not be deleted. If this is a ref count issue in the WIndows 8.1 DLLs, CodeJock should modify Free to see if any pane is a docking pane, if so get the container and remove any panes (especially that active pane) so the container doesn't crash. That's assuming another crash doesn't occur. I tried a try/catch around our OnPaint handler, which we override on the tabbed container and CJ just crashed elsewhere processing/filtering other messages. So perhaps a better thing to do in the Free code is to trap those base panes that have a hWnd and destroy the window.

Oh, and our app isn't crashing either. Still have testing to do after I restore a bunch of code I commented out that create docking panes. We have a lot of them among the 5 MDI doc types and I did that due to the amazing amount of pane creations and deletions CJ does when loading a layout.
Back to Top
rdhd View Drop Down
Senior Member
Senior Member
Avatar

Joined: 13 August 2007
Location: United States
Status: Offline
Points: 605
Post Options Post Options   Thanks (1) Thanks(1)   Quote rdhd Quote  Post ReplyReply Direct Link To This Post Posted: 15 April 2015 at 9:42am
Unfortunately people rely on uiautomation to drive our app (from .NET for automatic testing procedures). So even though I tested the theory that not giving out the IAccessible interface "fixed" the problem, it isn't the solution.

According to the CJ ref guide, DeletePane is called to destroy the pane. Even though DeletePane is a virtual method defined by the pane base class, CXTPDockingPaneTabbedContainer overrides it but doesn't make it virtual.

So I either have to modify that class and make it virtual, or I go into the layout object's Free class and call DestroyWindow. I did that and it avoids the crash.

I also noted in the sample that the "DockingPane" menu is a command bar and it too gives out an IAccessible interface. So I went into the MFC oleunk.cpp file and set a conditional breakpoint in ExternalAddRef to watch the ref count there. Each time I click the menu, a keyboard hook implemented by uiautomation starts querying and add ref'ing the interface. Disable the break point and then click and dismiss the menu for a while then enable the breakpoint and look at the ref count. The count just keeps increasing and increasing reaching the hundreds quite quickly. Hence I believe my suspicion that on Windows 8.1, Windows is leaking reference counts is correct.

The change to call DestroyWindow keeps the app from crashing and I don't really have another ideal on what else can be done. So either edit the tabbed container's include file to make DeletePane virtual and override the class and implement DeletePane to call DestroyWindow and then the base class DeletePane, or modify the Free method and call DestroyWindow before calling DeletePane (order is important since DeletePane can cause a pane to be deleted if the ref count is not going crazy). Note the "accessible" object isn't really the tabbed container but the container still gets a lot of references on it too.
Back to Top
mcmastl View Drop Down
Admin Group
Admin Group
Avatar

Joined: 14 April 2015
Status: Offline
Points: 79
Post Options Post Options   Thanks (0) Thanks(0)   Quote mcmastl Quote  Post ReplyReply Direct Link To This Post Posted: 16 April 2015 at 2:00pm
We have informed our development team of the issue and will be looking into it.  Thank you for bringing this to our attention.  If the issue has been resolved please let us know.  
Luke McMasters, Support Team
CODEJOCK SOFTWARE SOLUTIONS
Back to Top
 Post Reply Post Reply
  Share Topic   

Forum Jump Forum Permissions View Drop Down



This page was generated in 0.094 seconds.