Fixed: the server would freeze after running for long enough due to an integer overflow in SERVER_Tick, and some cleanup
This addresses the ticket: https://zandronum.com/tracker/view.php?id=822, here's a summary of the issue:
-
When the server's been running long enough, eventually
I_MSTime
(returnsunsigned int
) overflows which results in the "now" time becoming less than the "previous" (i.e.g_lGameTime
) time. -
Since
SERVER_Tick
previously used signed integers instead of the more appropriate unsigned integers, when the overflow occurs the "now" time becomes negative, so when "new" ticks is calculated it also becomes an incredibly large negative number. -
The server then hangs when subtracting the incredibly small "new" ticks by the incredibly large "previous" ticks in a while loop:
lCurTics = lNewTics - lPreviousTics; while ( lCurTics <= 0 )
I mostly solved this problem by changing all of these integers to unsigned, which also means the overflow happens once every ~49 days of constant server run time instead of ~24 days. Something worth noting is that I added a global g_GameTicShift
variable to ensure that the server's tick rate always remains at 35 ticks per 1000 ms after an overflow occurs. I added documentation in the new helper function server_GetDeltaTicks
to explain the whole process of doing this.
Some refactoring and cleanup was also necessary. Adding the constant MS_TO_TICKS
and the function server_GetDeltaTicks
removed some of the duplicated code that existed before.