Handle system time sampling failures safely.

This commit is contained in:
Bartosz Taudul
2026-11-04 19:06:15 +01:00
parent 453ecc3b74
commit 094be55320
2 changed files with 38 additions and 22 deletions
+35 -20
View File
@@ -26,7 +26,7 @@ static inline uint64_t ConvertTime( const FILETIME& t )
return ( uint64_t( t.dwHighDateTime ) << 32 ) | uint64_t( t.dwLowDateTime );
}
void SysTime::ReadTimes()
bool SysTime::ReadTimes()
{
FILETIME kernelTime;
FILETIME userTime;
@@ -35,13 +35,13 @@ void SysTime::ReadTimes()
FILETIME creationTime;
FILETIME exitTime;
GetProcessTimes( GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime );
if( !GetProcessTimes( GetCurrentProcess(), &creationTime, &exitTime, &kernelTime, &userTime ) ) return false;
idle = 0;
# else
FILETIME idleTime;
GetSystemTimes( &idleTime, &kernelTime, &userTime );
if( !GetSystemTimes( &idleTime, &kernelTime, &userTime ) ) return false;
idle = ConvertTime( idleTime );
# endif
@@ -49,52 +49,58 @@ void SysTime::ReadTimes()
const auto kernel = ConvertTime( kernelTime );
const auto user = ConvertTime( userTime );
used = kernel + user;
return true;
}
# elif defined __linux__
void SysTime::ReadTimes()
bool SysTime::ReadTimes()
{
uint64_t user, nice, system;
uint64_t user, nice, system, idleTicks;
FILE* f = fopen( "/proc/stat", "r" );
if( f )
{
int read = fscanf( f, "cpu %" PRIu64 " %" PRIu64 " %" PRIu64" %" PRIu64, &user, &nice, &system, &idle );
fclose( f );
if (read == 4)
{
used = user + nice + system;
}
}
if( !f ) return false;
const int read = fscanf( f, "cpu %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &user, &nice, &system, &idleTicks );
fclose( f );
if( read != 4 ) return false;
used = user + nice + system;
idle = idleTicks;
return true;
}
# elif defined __APPLE__
void SysTime::ReadTimes()
bool SysTime::ReadTimes()
{
host_cpu_load_info_data_t info;
mach_msg_type_number_t cnt = HOST_CPU_LOAD_INFO_COUNT;
host_statistics( mach_host_self(), HOST_CPU_LOAD_INFO, reinterpret_cast<host_info_t>( &info ), &cnt );
if( host_statistics( mach_host_self(), HOST_CPU_LOAD_INFO, reinterpret_cast<host_info_t>( &info ), &cnt ) != KERN_SUCCESS ) return false;
used = info.cpu_ticks[CPU_STATE_USER] + info.cpu_ticks[CPU_STATE_NICE] + info.cpu_ticks[CPU_STATE_SYSTEM];
idle = info.cpu_ticks[CPU_STATE_IDLE];
return true;
}
# elif defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __DragonFly__
void SysTime::ReadTimes()
bool SysTime::ReadTimes()
{
u_long data[5];
size_t sz = sizeof( data );
sysctlbyname( "kern.cp_time", &data, &sz, nullptr, 0 );
if( sysctlbyname( "kern.cp_time", &data, &sz, nullptr, 0 ) != 0 ) return false;
used = data[0] + data[1] + data[2] + data[3];
idle = data[4];
return true;
}
#endif
SysTime::SysTime()
: idle( 0 )
, used( 0 )
, haveBaseline( false )
{
ReadTimes();
haveBaseline = ReadTimes();
}
float SysTime::Get()
@@ -102,7 +108,16 @@ float SysTime::Get()
const auto oldUsed = used;
const auto oldIdle = idle;
ReadTimes();
if( !ReadTimes() )
{
haveBaseline = false;
return -1;
}
else if( !haveBaseline )
{
haveBaseline = true;
return -1;
}
const auto diffIdle = idle - oldIdle;
const auto diffUsed = used - oldUsed;
+3 -2
View File
@@ -18,10 +18,11 @@ public:
SysTime();
float Get();
void ReadTimes();
private:
bool ReadTimes();
uint64_t idle, used;
bool haveBaseline;
};
}