CXTPToolTIpContextToolTip::OnDestroy and a crash |
Post Reply |
Author | |
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
Posted: 04 December 2013 at 11:59am |
I am using an html tooltip and every so often I crash in CXTPTooltipContextToolTip::SetVisible. I suspect that the window is invalid when the OnTimer call comes through.
So I followed the destroy window call until I got to CXTPToolTipContextToolTip::OnDestroy. There I found this: KillTimer(1); // should fix a potential crash I see that m_arrTools has a size of zero. In OnTimer I see nIDEvent is 1. But m_nDelayTimer is zero. But the code path to SetVisibleTool has to pass "if (nIDEvent == m_nDelayTimer)" But neither FindTool nor SetVisibleTool change the value of m_nDelayTimer. Furthermore the TOOLITEM* pVisibleTool passed to SetVisibleTool looks like it is invalid (possibly deleted) memory at the time of the crash (in this particular case I am crashing in in the pWnd->ClientToScreen call SetVisibleTool makes. The call to GetToolSize in SetVisibleTool has already been made and the size looks valid. This isn't the only place I have crashed. For example, I have also crashed during the tool copy code (invalid string pointer causing ATL string class to try and allocate huge memory buffers). I am led to believe the tool passed into SetVisibleTool was valid when passed in and then somehow got deleted from m_arrTools during the processing but have been unable to verify that. This isn't easy to reproduce. I have to move around the ribbon quickly quite a bit and a key to making it crash seems to be to click the application button and move over the menus. Also I try to avoid the timer going off so that I see the tip display on the app button/menu. I found that as I move over the app button and menus the context object calls DestroyWindow, which led me to OnDestroy. Can someone at CodeJock explain the nature of the crash the comment refers to that led to the KillTimer call in OnDestroy? Could the tooltip formatting code be causing a delay or allowing addition message processing that is causing this issue? |
|
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
|
I have verified that the tool is being deleted while it is being used. I implemented OnTimer and OnDelTool and copied the code. I added trace calls to print out the pointer to the item.
When I crash I can see that the timer ran and I had a good tool pointer. Then when I crashed I can see the pointer being used during the OnTimer code execution is still the same. I also see the trace statement from OnDelTool where I printed out the same tool pointer that was being deleted. So how does this happen? TTM_DELTOOL is invoked via a SendMessage in the tooltip context code. Somehow the frame is processing messages while processing a tool hit and preparing to display the tooltip. That led me to the HTML tooltip code where Navigate is called. The code for the call to Navigate is followed by a do loop where AfxGetApp()->PumpMessage is called until get_ReadyState returns READYSTATE_COMPLETE. That is allowing the frame to process mouse moves and when I move the mouse off the current control on the ribbon to another control the code sends the TTM_DELTOOL message. Kaboom. I'm not sure I want that PumpMessage call. The larger the html page is the longer it takes to process and the longer that takes the greater the risk of this occurring. So what is the purpose of PumpMessage in the HTML tooltip code? Or, what would a CodeJock programmer do to avoid this situation? Note the TTM_DELTOOL call by seeing if the tool is still valid after Navigate? My current crash is in the Assign call in SetVisibleTool (actually in CSimpleString = operator) and after calling EnsureVisible that would be the time to make sure the pointer is still valid. Other options? Make a copy of the tool before calling EnsureVisible and using the copy after that call and hope the window of the tool itself is still valid (seems like a safe assumption). |
|
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
|
Just a quick correction:
GetToolSize is where Navigate is called not EnsureVisible. SetVisibleTool calls GetToolSize and when that routine returns the tool can be deleted due to the PumpMessage calls. |
|
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
|
This call to PumpMessage is more dangerous than I realized. It looks like a user can close the app at just the wrong moment and the commandbars object gets destroyed, which destroys the tooltip context, which destroys the tool context tooltip ...
I have also noticed a crash where the vtable of the html tooltip class is bad (function call to random code). In that case I got a dump and found that OnTimer was on the stack three times when the crash occurred. In each case the call went to the GetToolSize and PumpMessage call. I tried removing PumpMessage and get_readystate never indicated a ready state (locked in infinite loop). So now I am trying to copy the browser app com interface (with an AddRef) and using the copy in the GetToolSize method so I don't access a bad instance pointer when ready state is signaled and trying to figure out how to handle unwinding the stack if something goes wrong (like the html tooltip destructor fires while in a method on the object). |
|
markr
Senior Member Joined: 01 August 2004 Status: Offline Points: 443 |
Post Options
Thanks(0)
|
Have you had any luck in figuring this out? I'm seeing the problem as well.
|
|
astoyan
Admin Group Joined: 24 August 2013 Status: Offline Points: 304 |
Post Options
Thanks(0)
|
The issue has been addressed and fixed for the next release. Should you want to re-test, CPU Stress utility (http://blogs.msdn.com/b/vijaysk/archive/2012/10/27/tools-to-simulate-cpu-memory-disk-load.aspx) will help to re-produce the crash faster. If you notice that the issue is not resolved or crashes in another place, please let me know, because catching and debugging this one was not an easy task and some scenarios still might remain unresolved. Thank you.
|
|
markr
Senior Member Joined: 01 August 2004 Status: Offline Points: 443 |
Post Options
Thanks(0)
|
> The issue has been addressed and fixed for the next release.
Well, that's definitely good news. Would the bug you fixed affect markup tooltips as well?
|
|
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
|
Astoyan,
We have pulled 17 (beta 3). We have also implemented MDI tabs for our MDI application. We have been crashing when running with HTML tooltips and I am examining the problem and here is what I see. I right-click on the tab and bring up a shortcut menu and move over an element. The tooltip timer fires and the HTML tooltip code calls Navigate. Then it goes into the PumpMessage loop. While inside the loop, I move the mouse off the context menu. The tooltip context object's FilterToolTipMessageHelper calls SAFE_DELETEWINDOW(m_pToolTip). The destructor for the HTML tooltip calls SAFE_RELEASE(m_pBrowserApp) and the browser app gets deleted and the pointer is set to NULL. Then the ready state for the Navigate calls fires. The deleted HTMLTooltip then tries to access the deleted m_pBrowserApp member and the app crashes. I have set break points in the code and printed messages so I don't interrupt the timing. What I see is something like this (number of calls to get_ReadyState varies, of course): "navigating browser 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "calling get_ReadyState on 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" "Deleting browser 0x0000000073916250 <No type information available in symbol file for ieframe.dll>" f:\dd\vctools\vc7libs\ship\atlmfc\src\mfc\cmdtarg.cpp(40) : Assertion failed! "calling get_ReadyState on 0x0000000000000000 <NULL>" Let me note that we have been rarely crashing in the past with the same call stack. Also, users have reported, and I have examined dumps, for cases where the user is moving over and clicking the app close button (upper-right "x"). In those cases, it appears the tooltip context itself has been destroyed while we are in the PumpMessage loop. Basically what I don't see, or at least understand, is how CodeJock is trying to prevent the deletion of the HTML tooltip while in the PumpMessage loop. I don't see any calls to AddRef/Release on the HTML tooltip. Shouldn't the call to delete really be a call to Release. Then at least when the timer event occurs, the HTML tooltip could itself call AddRef and then Release when exiting the timer handler. Also in the PumpMessage loop, the HTML tooltip could check the m_cRef member and if it is one, assume it should cancel the navigation is exit (to prevent the tip from displaying after the user has moved on). What do you think? By the way, I did see the posting of the tool delete message to address the other issue I first brought up. |
|
rdhd
Senior Member Joined: 13 August 2007 Location: United States Status: Offline Points: 886 |
Post Options
Thanks(0)
|
Astoyan,
Can you tell me what the fix was you mentioned? |
|
Post Reply | |
Tweet
|
Forum Jump | Forum Permissions You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum |