CodePlexProject Hosting for Open Source Software

1

Vote
http://topaz.codeplex.com/SourceControl/latest#source/Source/TransientFaultHandling/ExponentialBackoff.cs breaks down
with an unchecked integer overflow due to casting the delta to an int.

Plug in for example the following constants:

deltaBackoff = 1s

minBackoff = 1s

maxBackoff = 60s

retry delta (ms) interval (ms)

1 1086 2086

2 2979 3979

3 5635 6635

4 16815 17815

5 26288 27288

6 74466 60000

7 129413 60000

8 283050 60000

9 542171 60000

10 874665 60000

11 1678540 60000

12 3714165 60000

13 8805325 60000

14 14810232 60000

15 35290059 60000

16 54262980 60000

17 154925922 60000

18 276036579 60000

19 457702551 60000

20 991951950 60000

21 -2147483648 -2147482648 <- integer overflow

...

Which means that after the 20th retry the interval becomes 0 and goes into a busy loop, assuming you're allowing enough retries.

The fix is to remove the cast to int, i.e.:

var delta = (int)((Math.Pow(2.0, currentRetryCount) - 1.0) ...

should be

var delta = (Math.Pow(2.0, currentRetryCount) - 1.0) ...

The 'checked' block on interval is also redundant:

var interval = (int)Math.Min(checked(this.minBackoff.TotalMilliseconds + delta), this.maxBackoff.TotalMilliseconds);

could be:

var interval = (int)Math.Min(this.minBackoff.TotalMilliseconds + delta, this.maxBackoff.TotalMilliseconds);

since as delta approaches Infinity, Math.Min will just return maxBackoff.

Plug in for example the following constants:

deltaBackoff = 1s

minBackoff = 1s

maxBackoff = 60s

retry delta (ms) interval (ms)

1 1086 2086

2 2979 3979

3 5635 6635

4 16815 17815

5 26288 27288

6 74466 60000

7 129413 60000

8 283050 60000

9 542171 60000

10 874665 60000

11 1678540 60000

12 3714165 60000

13 8805325 60000

14 14810232 60000

15 35290059 60000

16 54262980 60000

17 154925922 60000

18 276036579 60000

19 457702551 60000

20 991951950 60000

21 -2147483648 -2147482648 <- integer overflow

...

Which means that after the 20th retry the interval becomes 0 and goes into a busy loop, assuming you're allowing enough retries.

The fix is to remove the cast to int, i.e.:

var delta = (int)((Math.Pow(2.0, currentRetryCount) - 1.0) ...

should be

var delta = (Math.Pow(2.0, currentRetryCount) - 1.0) ...

The 'checked' block on interval is also redundant:

var interval = (int)Math.Min(checked(this.minBackoff.TotalMilliseconds + delta), this.maxBackoff.TotalMilliseconds);

could be:

var interval = (int)Math.Min(this.minBackoff.TotalMilliseconds + delta, this.maxBackoff.TotalMilliseconds);

since as delta approaches Infinity, Math.Min will just return maxBackoff.

No files are attached

## comments