summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Warner <james.warner@comcast.net>2023-03-01 00:00:00 -0600
committerCraig Small <csmall@dropbear.xyz>2023-03-02 19:38:41 +1100
commit133a833942224a9ae4cd049d62a3fa54e95c5a2a (patch)
treef8a8e1e15aef55de481aec5b2d13d5e4df70cb50
parent8c81808de09b034c5dc2221aacc85d25c3218676 (diff)
downloadprocps-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.c28
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 |