Upstream-Status: Pending fix that top will quit after cpu offline top utiliy fails to read /proc/stat after cpu offline, because Cpu_tot is still the original cpu numbers when calling cpus_refresh, in which it is trying to read and sscanf Cpu_tot times /proc/stat. The patch is from procps-3.2.8-2.fc12.src.rpm Signed-off-by: Wenzong Fan --- --- procps-3.2.7/top.c.remcpu 2006-07-10 10:41:11.000000000 +0200 +++ procps-3.2.7/top.c 2006-07-10 10:41:35.000000000 +0200 @@ -912,6 +912,7 @@ static CPU_t *cpus_refresh (CPU_t *cpus) { static FILE *fp = NULL; + static int cpu_max; int i; int num; // enough for a /proc/stat CPU line (not the intr line) @@ -926,24 +927,29 @@ can hold tics representing the /proc/stat cpu summary (the first line read) -- that slot supports our View_CPUSUM toggle */ cpus = alloc_c((1 + Cpu_tot) * sizeof(CPU_t)); + cpu_max = Cpu_tot; } + else if (cpu_max > Cpu_tot) + /* move saved CUPs summary to cpu_max possition */ + memcpy(&cpus[cpu_max], &cpus[Cpu_tot], sizeof(CPU_t)); + rewind(fp); fflush(fp); // first value the last slot with the cpu summary line if (!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read"); - cpus[Cpu_tot].x = 0; // FIXME: can't tell by kernel version number - cpus[Cpu_tot].y = 0; // FIXME: can't tell by kernel version number - cpus[Cpu_tot].z = 0; // FIXME: can't tell by kernel version number + cpus[cpu_max].x = 0; // FIXME: can't tell by kernel version number + cpus[cpu_max].y = 0; // FIXME: can't tell by kernel version number + cpus[cpu_max].z = 0; // FIXME: can't tell by kernel version number num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu", - &cpus[Cpu_tot].u, - &cpus[Cpu_tot].n, - &cpus[Cpu_tot].s, - &cpus[Cpu_tot].i, - &cpus[Cpu_tot].w, - &cpus[Cpu_tot].x, - &cpus[Cpu_tot].y, - &cpus[Cpu_tot].z + &cpus[cpu_max].u, + &cpus[cpu_max].n, + &cpus[cpu_max].s, + &cpus[cpu_max].i, + &cpus[cpu_max].w, + &cpus[cpu_max].x, + &cpus[cpu_max].y, + &cpus[cpu_max].z ); if (num < 4) std_err("failed /proc/stat read"); @@ -955,7 +961,7 @@ } // now value each separate cpu's tics - for (i = 0; 1 < Cpu_tot && i < Cpu_tot; i++) { + for (i = 0; ; i++) { if (!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read"); cpus[i].x = 0; // FIXME: can't tell by kernel version number cpus[i].y = 0; // FIXME: can't tell by kernel version number @@ -964,9 +970,35 @@ &cpus[i].id, &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i, &cpus[i].w, &cpus[i].x, &cpus[i].y, &cpus[i].z ); - if (num < 4) - std_err("failed /proc/stat read"); + if (num < 4) { + Cpu_tot = i; + break; + } + if (i == cpu_max - 1) { + // Bump cpu_max and extend cpus + cpu_max++; + cpus = realloc(cpus, (1 + cpu_max) * sizeof(CPU_t)); + if (!cpus) std_err("realloc failed"); + memcpy(&cpus[cpu_max], &cpus[cpu_max-1], sizeof(CPU_t)); + } + } + + if (cpu_max > Cpu_tot) + memcpy(&cpus[Cpu_tot], &cpus[cpu_max], sizeof(CPU_t)); + + // and just in case we're 2.2.xx compiled without SMP support... + if (Cpu_tot == 1) { + cpus[0].id = cpus[1].id = 0; + cpus[0].u = cpus[1].u; + cpus[0].n = cpus[1].n; + cpus[0].s = cpus[1].s; + cpus[0].i = cpus[1].i; + cpus[0].w = cpus[1].w; + cpus[0].x = cpus[1].x; + cpus[0].y = cpus[1].y; + cpus[0].z = cpus[1].z; } + return cpus; }