Bug:Ctrl Wheel Crash

James:

Ed - Thanks for the stack trace - very helpful.

In Ruler.cpp line 1029, in this line UPP can become a NaN (a 'not-a-number') double UPP = (mMax-mMin)/mLength

Most likely that's from mLength being zero. Ed, the way to check that theory is to put a test like:

if( mLength < 0.000000000000001 ) mLength=mLength;

There, and put a breakpoint on the assignment. In temporary debugging code this works better than an ASSERT because when you hit the breakpoint it is easy to check the values of other variables.

The NaN is passed to the 'FindLinearTickSizes', which does not cope with it gracefully. In XP I can scroll out to 312 hours, or in to about 8 samples across the full screen width. It's intriguing that Win7 should behave differently.

This code TrackPanel.cpp line 4158

if (steps < 0) mViewInfo->zoom = wxMax(mViewInfo->zoom / (2.0 * -steps), gMinZoom); else mViewInfo->zoom = wxMin(mViewInfo->zoom * (2.0 * steps), gMaxZoom);

Is what limits the range in XP.
 * It's just possible the problem isn't so much the mouse wheel itself, and that the same issue can be got by zooming out too far in Win7 using the magnifier button. It's just that the mouse wheel makes it very easy to do that.  In that case it's likely the root cause is that XP is making very big or very small numbers where Vista makes NaNs.  Ed, could you try that?
 * Another possibility is that for Vista and Win7 in HandleWheelRotation steps can take values, like negative zero, that are not possible in WinXP. The NaN so produced could defeat the wxMin or wxMax.  Again the same trick of creating a place for putting a breakpoint can be used to track that down.

Al:

First, I can't reproduce this in Windows 7 (x86-64). I don't know why...

Ruler::mLength is an int. There's a test for (mLength <= 0) earlier up in Ruler::Update. So I doubt mLength is 0. Furthermore, division by 0 in IEEE floating point should give an infinite value, not NaN (unless the numerator is also zero). I'd guess mMin or mMax was NaN coming in to the calculation.

In TrackPanel::HandleWheelRotation steps is an int also, so it can't be -0 or NaN. But it could be 0. And that would cause mViewInfo.zoom to be set to 0. That might cause this problem -- Ruler's mMin and mMax are set according to values calculated in AdornedRulerPanel::DoDrawMarks, where mViewInfo.zoom is in the denominator (there are some other calculations that might cause it to go NaN instead of INF). I'll send a patch to Ed to test.

-- Ed 24 January 2010: 

I am headed to a client's in a few minutes to do a hardware install -- he has a slow 64-bit Windows 7 laptop; I will install 1.3.11 on it and give it a try.

After applying Al's patch scrolling the mouse wheel while holding down the control button did not crash or Assert but it also did not zoom.

Ruler.cpp near line number 500: case RealFormat: d = 0.000001; // mDigits is number of digits after the decimal point. mDigits = 6; for { if (units < d) { mMinor = d;           mMajor = d*5.0; return; }        d *= 5.0; if (units < d) { mMinor = d;           mMajor = d*2.0; return; }        d *= 2.0; mDigits--; if( mDigits < -9.9999999999991 )/*    efm5     debug     */ double bug2=mDigits; // More than 10 digit numbers? Something is badly wrong. // Probably units is coming in with too high a value. //wxASSERT( mDigits >= -10 );/*    efm5     debug     */ }

after reverting Al's patch, I commented out the Assert so that instead of entering the debugger I would see the crash which happens when I run the non-debug code. What happened was that the program got stuck in the for { loop. There might be some interesting information here (read the following information in the edit section to maintain formatting and readability):

d	1.#INF000000000000	double mDigits	-101508838	int -		this	0x04b3a900 {mbTicksOnly=true mbTicksAtExtremes=false mRect={...} ...}	Ruler * const mbTicksOnly	true	bool mbTicksAtExtremes	false	bool +		mRect	{x=0 y=0 width=1779 ...}	wxRect +		mTickColour	{m_pixel=33554432 m_isInit=true m_red=0 ...}	wxColour +		mPen	{...}	wxPen mMaxWidth	1779	int mMaxHeight	0	int mLeft	1	int mTop	1	int mRight	1780	int mBottom	25	int mLead	0	int mLength	1779	int mLengthOld	1779	int +		mDC	0x01ddf0bc {m_paintdc={...} }	wxDC * +		mMinorFont	0x04b35370	wxFont * +		mMajorFont	0x04b7dcd8	wxFont * +		mMinorMinorFont	0x04b3ac60	wxFont * mUserFonts	false	bool mMin	-1.#IND000000000000	double mMax	-1.#IND000000000000	double mMajor	1.0000000000000000	double mMinor	0.50000000000000000	double mDigits	-101508838	int +		mUserBits	0x00000000	int * +		mBits	0x04b78528	int * mUserBitLen	0	int mValid	false	bool mNumMajor	0	int +		mMajorLabels	0x04b636ac {pos=132 lx=123 ly=6 ...}	Ruler::Label * mNumMinor	0	int +		mMinorLabels	0x04b6a62c {pos=24 lx=25 ly=21 ...}	Ruler::Label * mNumMinorMinor	0	int +		mMinorMinorLabels	0x04b715ac {pos=-842150451 lx=-842150451 ly=-842150451 ...}	Ruler::Label * mOrientation	4	int mSpacing	6	int mHasSetSpacing	false	bool mLabelEdges	false	bool mFormat	TimeFormat	Ruler::RulerFormat mLog	false	bool mFlip	false	bool mCustom	false	bool mbMinor	true	bool mMajorGrid	false	bool mMinorGrid	false	bool mGridLineLength	0	int +		mUnits	{...}	wxString units	-1.#IND000000000000	double

-- Ed 24 January 2010 in regard to James' suggestion for putting a breakpoint at the assignment, this is unworkable because this code is triggered by simply switching from the debugger window to the application window and the breakpoint is hit constantly when that happens.

Here are the first four lines of the call stack which results when I force a break of the above forever loop: >	Audacity.exe!Ruler::FindLinearTickSizes(double UPP=-1.#IND000000000000) Line 517 + 0x8 bytes	 Audacity.exe!Ruler::Update(Envelope * speedEnv=0x00000000, long minSpeed=0, long maxSpeed=0) Line 1040	 Audacity.exe!Ruler::Draw(wxDC & dc={...}, Envelope * speedEnv=0x00000000, long minSpeed=0, long maxSpeed=0) Line 1244	 Audacity.exe!Ruler::Draw(wxDC & dc={...}) Line 1229	 Audacity.exe!AdornedRulerPanel::DoDrawMarks(wxDC * dc=0x01ddf0bc, bool __formal=true) Line 1915	

Ed's report to Al
Al:

Can you use the scroll wheel without Ctrl held down to scroll up and down? Can you use the scroll wheel with Shift to scroll side-to-side? On my machine everything works OK with the patch, but everything works OK without it, too...

Clearly steps is coming out 0 for you in TrackPanel::HandleWheelRotation. But event.m_wheelRotation isn't 0, or else it never would have been called. Try breaking at TrackPanel::HandleWheelRotation and find the values for event.m_wheelRotation and event.m_wheelDelta.

-- Ed 24 January 2010

There's a lot of material to cover here...
 * I just use the web-based installer to do a "virgin" install 1.3.11 beta on a brand-new 64-bit Windows 7 laptop (1.6 GHz, single-core, 2 GB RAM) with a Logitech wireless mouse; I did not install any of the libraries like Lame or FFmpeg and no plug-ins. After starting Audacity I generated 30 seconds of noise so that I would have something to scroll in on. All the various mouse scroll knob functions worked just fine.


 * As per Al's request above I tried other uses of the scroll wheel on my 64-bit Windows 7 home machine (3 GHz quad-core 8 GB RAM, Microsoft wireless mouse) -- scrolling up and down was very problematical, it did not crash or Assert but it only worked at most 30% of the time and when it did work at all it was very jerky and usually it would stop responding fairly quickly; scrolling side to side was a little better, it did not crash nor Assert, it never stopped responding completely but was occasionally "hesitant".


 * Breaking TrackPanel::HandleWheelRotation near line 4157:

} else if (event.CmdDown) {     // MM: Zoom in/out when used with Control key down // MM: I don't understand what trackLeftEdge does int trackLeftEdge = GetLeftOffset; <- here

(This is not easy trying to carrying on a debugging conversation in this little tiny wiki editor window!) gives the following information for local variables:  new_center_h	-9.2559631349317831e+061	double center_h	-9.2559631349317831e+061	double trackLeftEdge	-858993460	int +		this	0x04b3cf08 {mLabelTrackStartXPos=-1 mLabelTrackStartYPos=-842150451 mTrackInfo={...} ...}	TrackPanel * const -		event	{m_x=767 m_y=192 m_leftDown=false ...}	wxMouseEvent & +		wxEvent	{m_eventObject=0x04b3cf08 m_eventType=10041 m_timeStamp=154564433 ...}	wxEvent m_x	767	int m_y	192	int m_leftDown	false	bool m_middleDown	false	bool m_rightDown	false	bool m_controlDown	true	bool m_shiftDown	false	bool m_altDown	false	bool m_metaDown	false	bool m_wheelRotation	30	int m_wheelDelta	120	int m_linesPerAction	4	int steps	0	int  (again look at the above information in edit to maintain formatting and readability -- it would be so much easier to attach a text file to e-mail)

Al:

It looks like the root cause here is pretty similar to the cause of this bug:. Ed has a mouse with a "high-resolution" scroll wheel and Audacity doesn't handle that correctly. The integer division 30/120 results in (steps == 0). I have a normal old mouse and only get wheel rotation events at multiples of m_wheelDelta.

It shouldn't be too hard to use fractional steps in TrackPanel... I'll check for other places where we handle mouse wheel events also.