added sv_minRebootDelayMins to control early server reboots

This commit is contained in:
myT 2017-05-23 23:42:02 +02:00
parent b49c880fe5
commit 1bd7614d21
2 changed files with 43 additions and 20 deletions

View file

@ -1,6 +1,8 @@
DD Mmm 17 - 1.49 DD Mmm 17 - 1.49
add: sv_minRebootDelayMins to control early server reboots (default: 1440, minimum: 60)
fix: broken rendering when the 2nd stage of a collapsed shader stage pair had non-white colors fix: broken rendering when the 2nd stage of a collapsed shader stage pair had non-white colors
fix: shader stages using "wave" were not animated when the server time was too large fix: shader stages using "wave" were not animated when the server time was too large

View file

@ -716,6 +716,18 @@ qbool SV_CheckPaused( void ) {
return qtrue; return qtrue;
} }
static void SV_IntegerOverflowShutDown( const char* msg )
{
// save the map name in case it gets cleared during the shut down
char mapName[MAX_QPATH];
Q_strncpyz( mapName, Cvar_VariableString("mapname"), sizeof(mapName) );
SV_Shutdown( msg );
Cbuf_AddText( va("map %s\n", mapName) );
}
/* /*
================== ==================
SV_Frame SV_Frame
@ -761,36 +773,45 @@ void SV_Frame( int msec ) {
return; return;
} }
int activeClients = 0; qbool hasHuman = qfalse;
for (int i=0; i < sv_maxclients->integer ; ++i) { for (int i=0; i < sv_maxclients->integer ; ++i) {
client_t *cl = &svs.clients[i];; client_t *cl = &svs.clients[i];
if ( cl->state >= CS_CONNECTED ) { if ( cl->state >= CS_CONNECTED ) {
qbool isBot = (cl->netchan.remoteAddress.type == NA_BOT) || (cl->gentity && (cl->gentity->r.svFlags & SVF_BOT)); const qbool isBot = (cl->netchan.remoteAddress.type == NA_BOT) || (cl->gentity && (cl->gentity->r.svFlags & SVF_BOT));
if (!isBot) if ( !isBot ) {
{ hasHuman = qtrue;
++activeClients;
break; break;
} }
} }
} }
// if time is about to hit the 32nd bit, kick all clients and clear svs.time // The shader time is stored as a floating-point number.
// rather than checking for negative time wraparound everywhere. // Some mods may still have code like "sin(cg.time / 1000.0f)".
// 2giga-milliseconds = 23 days, so it won't be too often // IEEE 754 floats have a 23-bit mantissa.
// // Rounding errors will start after roughly ((1<<23) / (60*1000)) ~ 139.8 minutes.
// shader startTime is float. And for animation CPMA use sin(cg.time / float). const int minRebootTimeCvar = 60 * 1000 * Cvar_Get( "sv_minRebootDelayMins", "1440", 0 )->integer;
// float have 23-bit integer part. Round error start after 2:20 hours const int minRebootTimeConst = 60 * 60 * 1000; // absolute min. time: 1 hour
// lets check 24 hours work const int maxRebootTime = 0x7FFFFFFF; // absolute max. time: ~ 24.86 days
unsigned timeLimit = activeClients ? 24 * 60 * 60 * 1000 : 10 * 60 * 1000; const int minRebootTime = max( minRebootTimeCvar, minRebootTimeConst );
if ( (unsigned)svs.time >= timeLimit ) { if ( svs.time >= minRebootTime && !hasHuman ) {
SV_Shutdown( "Restarting server due to time wrapping" ); SV_IntegerOverflowShutDown( "Restarting server early to avoid time wrapping and/or precision issues" );
Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) );
return; return;
} }
if ( minRebootTimeCvar < minRebootTimeConst )
Cvar_Set( "sv_minRebootDelayMins", va( "%d", minRebootTimeConst / (60 * 1000) ) );
// If the time is close to hitting the 32nd bit, kick all clients and clear svs.time
// rather than checking for negative time wraparound everywhere.
// No, resetting the time on map change like ioq3 does is not on the cards. It breaks stuff.
if ( svs.time >= maxRebootTime ) {
SV_IntegerOverflowShutDown( "Restarting server due to time wrapping" );
return;
}
// this can happen considerably earlier when lots of clients play and the map doesn't change // this can happen considerably earlier when lots of clients play and the map doesn't change
if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) { if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) {
SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" ); SV_IntegerOverflowShutDown( "Restarting server due to numSnapshotEntities wrapping" );
Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) );
return; return;
} }