diff options
author | Jim Warner <james.warner@comcast.net> | 2023-03-01 00:00:00 -0600 |
---|---|---|
committer | Craig Small <csmall@dropbear.xyz> | 2023-03-02 19:38:41 +1100 |
commit | 133a833942224a9ae4cd049d62a3fa54e95c5a2a (patch) | |
tree | f8a8e1e15aef55de481aec5b2d13d5e4df70cb50 | |
parent | 8c81808de09b034c5dc2221aacc85d25c3218676 (diff) | |
download | procps-ng-133a833942224a9ae4cd049d62a3fa54e95c5a2a.tar.gz |
library: become more tolerant of /proc/cpuinfo formats
In the issue referenced below, it is now apparent that
not all architectures follow a logical/expected format
for the /proc/cpuinfo file. Specifically, the expected
empty line after each processor entry might be missing
under some architectures for the last processor shown.
[ and a belated review of kernel source confirms it. ]
So this commit makes our stat module a little bit more
tolerant of some potential missing newline characters.
[ along the way, it's also now tolerant of a missing ]
[ cpuinfo file plus more efficient whenever a cpu is ]
[ is not linked to a core or toggled offline/online. ]
Reference(s):
https://gitlab.com/procps-ng/procps/-/issues/272
procps-ng/procps#272
Signed-off-by: Jim Warner <james.warner@comcast.net>
-rw-r--r-- | library/stat.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/library/stat.c b/library/stat.c index 0f88246..160223e 100644 --- a/library/stat.c +++ b/library/stat.c @@ -515,8 +515,9 @@ static int stat_cores_verify ( int a_cpu, a_core; FILE *fp; + // be tolerant of a missing CORE_FILE ... if (!(fp = fopen(CORE_FILE, "r"))) - return 0; + return 1; for (;;) { if (NULL == fgets(buf, sizeof(buf), fp)) break; @@ -525,12 +526,11 @@ static int stat_cores_verify ( continue; sscanf(buf, "processor : %d", &a_cpu); for (;;) { - if (NULL == fgets(buf, sizeof(buf), fp)) { - fclose(fp); - errno = EIO; - return 0; - } - if (buf[0] == '\n') { /* Entry for specific processor is finished */ + // be tolerant of missing empty line on last processor entry ... + if (NULL == fgets(buf, sizeof(buf), fp)) + goto wrap_up; + // be tolerant of a missing 'core id' on any processor entry ... + if (buf[0] == '\n') { a_core = a_cpu; break; } @@ -545,6 +545,7 @@ static int stat_cores_verify ( return 0; } } +wrap_up: fclose(fp); stat_cores_check(info); return 1; @@ -785,6 +786,8 @@ reap_em_again: cpu_ptr = info->cpus.hist.tics + i; // adapt to relocated if reap_em_again do { + static int once_sw; + bp = 1 + strchr(bp, '\n'); // remember this cpu from last time around memcpy(&cpu_ptr->old, &cpu_ptr->new, sizeof(struct stat_jifs)); @@ -806,14 +809,17 @@ reap_em_again: } stat_derive_unique(cpu_ptr); + // force a one time core link for cpu0 (if possible) ... + if (!once_sw) + once_sw = cpu_ptr->saved_id = -1; + /* this happens if cpus are taken offline/brought back online so we better force the proper current core association ... */ if (cpu_ptr->saved_id != cpu_ptr->id) { - cpu_ptr->saved_id = cpu_ptr->id; - cpu_ptr->core = NULL; - } - if (!cpu_ptr->core) + cpu_ptr->saved_id = cpu_ptr->id; + cpu_ptr->core = NULL; stat_cores_link(info, cpu_ptr); + } #ifdef CPU_IDLE_FORCED // first time through (that priming read) sum_ptr->edge will be zero | |