Skip to content

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:

  1. When the server's been running long enough, eventually I_MSTime (returns unsigned int) overflows which results in the "now" time becoming less than the "previous" (i.e. g_lGameTime) time.

  2. 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.

  3. 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.

Edited by Adam Kaminski

Merge request reports