AmqpSettings IdleTimeout error in case you time travel
optimuserik opened this issue · comments
AmqpSettings.IdleTimeout is set to int, but used as a uint
public int IdleTimeout
{
get;
set;
}
IdleTimeOut = (uint)amqpSettings.IdleTimeout / 2
We may want to change the BIOS time, and if we set it to a past time this will cause issues.
When checking elapsed time
Line 961 in 3e42f0c
uint elapsed = (uint)((now.Ticks - last.Ticks) / Encoder.TicksPerMillisecond);
the substraction can go into negative, since you time traveled and it will be a very high uint number.
Since IdleTimeout is by default set to int.MaxValue
IdleTimeout = int.MaxValue,
which presumably is intended to mean that it 'never' times out ( which would be what we want).
However the previously mentioned
uint elapsed = (uint)((now.Ticks - last.Ticks) / Encoder.TicksPerMillisecond);
will still be higher than the int.MaxValue, that is the default, resulting in GetDueMiliseconds to return 0,
due = timeout > elapsed ? timeout - elapsed : 0;
which then closes the connection and throws the exception.
Line 919 in 3e42f0c
if (thisPtr.local > 0 &&
GetDueMilliseconds(thisPtr.local, now, thisPtr.lastReceive) == 0)
{
thisPtr.connection.CloseInternal(
0,
new Error(ErrorCode.ConnectionForced)
{
Description = Fx.Format("Connection closed after idle timeout {0} ms", thisPtr.local)
});
thisPtr.SetTimerForClose();
return;
}
It would seem that the underlying issue is that AmqpSettings.IdleTimeout is an int but is used as uint.
Changing it to uint and initializing it with
IdleTimeout = uint.MaxValue,
would fix this issue and would probably be more in line with how it is actually used.
Changing the IdleTimeout might result in a breaking change though.
commit 54554af solves the issue.
Thank you.