#664208 xfce4-cpugraph-plugin: System load graph shows 100% load on unloaded cores, but cores are actually idle

Package:
xfce4-cpugraph-plugin
Source:
xfce4-cpugraph-plugin
Description:
CPU load graph plugin for the Xfce4 panel
Submitter:
RandomCore
Date:
2014-10-07 21:57:05 UTC
Severity:
normal
#664208#5
Date:
2012-03-16 16:52:42 UTC
From:
To:
Dear Maintainer,

I have xfce4-cpugraph-plugin configured to show a graph for ALL cores
(I'm currently running a 6 core AMD CPU). On the idle system the graph
shows a usage of nearly 100%, as the tooltip on the graph area says as well.

If I chose a single core to display in the graph all seems well, but
switching back to "ALL" the graph gets "loaded" again.

I had a peak in the source and found that the plugin uses the values
from /proc/stat beginning with "cpu" to calculate the usage. After
86days of uptime those values for "cpu" (the summary for all cores) get
quite large:
------CUT------
# cat /proc/stat
cpu  69142289 4481985 46463581 4342043951 11291324 31445 873288 0 268929 0
cpu0 18724487 749359 20399968 703944470 1821744 0 35392 0 43545 0
cpu1 16300038 768942 7712109 718527326 2313696 0 58316 0 55763 0
cpu2 9349518 735007 2562932 731107820 1894374 2 60586 0 57471 0
cpu3 5995803 742693 2093307 734958181 1914908 24 18773 0 49460 0
cpu4 5015592 712153 1625294 737134417 1187895 415 67749 0 33366 0
cpu5 13756849 773828 12069968 716371735 2158705 31001 632469 0 29321 0
intr 7326358500 3664851343 10725376 0 0 4 0 0 1 0 2 0 0 0 0 0 0 73332665 24150490 267630200 146 416608742 114341064 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 131377555 98607359 103428341 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 !
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 10337940883
btime 1324456956
processes 9513146
procs_running 2
procs_blocked 0
softirq 8903230587 0 1052949062 14175727 239913213 139296464 0 9989661 844769443 6050983 2301118738
------CUT------

I would guess, that the values are just too large to do the calculation
right anymore.

// ...
if( sscanf( cpuStr, "%*s %lu %lu %lu %lu %lu %lu %lu", &user, &nice, &system, &idle, &iowait, &irq, &softirq ) < 7 )
        iowait = irq = softirq = 0;
used = user + nice + system + irq + softirq;
total = used + idle + iowait;
if( (total - data[line].previous_total) != 0 )
{
        data[line].load = CPU_SCALE * (used - data[line].previous_used) /
                              (total - data[line].previous_total);
} //...

iIf I try this with the values above:

used = 69142289+4481985+46463581+31445+873288 = 120992588 (or 0x736334C)
total = used + 4342043951+11291324 = 179360567 (or 0xAB0D337)

If we assume user changed by 100 from the previous values

  load = 256*(120992588-120992488/(179360567-179360467)) =  30664361758 (or 0x723BD071E)

which is more than 64bit can hold.

And then, I may be wrong, because I actually just peaked into the
source and don't understand it at all..

#664208#10
Date:
2012-03-16 18:40:32 UTC
From:
To:
Dear Maintainer,

the calculation n my first message is completely bogus because I got the
parenthesis wrong. Sorry.

while true; do grep "^cpu " /proc/stat; sleep 0.5;done\
|awk '{
 used=$2+$3+$4+$7+$8
 total=used+$5+$6
 printf "used=%ld total=%ld load=%ld\n", used, total,
       256*(used-prevused)/(total-prevtotal)
 prevused=used
 prevtotal=total
}'

This gives values of around 5 for the idle machine. So, that's not it.

cu, Stefan

#664208#15
Date:
2012-03-16 19:29:29 UTC
From:
To:
Dear Maintainer,

I had time to compile it and did sometesting.

It turns out, that the total value exceeds the 32bit unsigned data size
of gulong:

$ while true; do grep "^cpu " /proc/stat; sleep 0.5;done|awk '{ used=$2+$3+$4+$7+$8; total=used+$5+$6; printf "used=%ld total=%ld load=%ld\n",used,total,256*(used-prevused)/(total-prevtotal);prevused=used;prevtotal=total}'
used=121149519 total=4480532061 load=6
used=121149529 total=4480532362 load=8
used=121149537 total=4480532651 load=7
used=121149547 total=4480532929 load=9
used=121149557 total=4480533268 load=7
used=121149568 total=4480533570 load=9
used=121149577 total=4480533821 load=9
used=121149590 total=4480534188 load=9

cu, Stefan

#664208#20
Date:
2012-03-16 21:13:24 UTC
From:
To:
If you change the gulong to calc into guint64 and the sscanf() accordingly, it works again:
--- os.c.orig 2010-11-07 13:58:22.000000000 +0100 +++ os.c 2012-03-16 21:59:03.941257947 +0100 @@ -94,7 +94,7 @@ gboolean read_cpu_data( CpuData *data, g { FILE *fStat; gchar cpuStr[PROCMAXLNLEN]; - gulong user, nice, system, idle, used, total, iowait, irq, softirq; + guint64 user, nice, system, idle, used, total, iowait, irq, softirq; guint line; if( !(fStat = fopen( PROC_STAT, "r" )) ) @@ -109,7 +109,7 @@ gboolean read_cpu_data( CpuData *data, g fclose( fStat ); return FALSE; } - if( sscanf( cpuStr, "%*s %lu %lu %lu %lu %lu %lu %lu", &user, &nice, &system, &idle, &iowait, &irq, &softirq ) < 7 ) + if( sscanf( cpuStr, "%*s %Lu %Lu %Lu %Lu %Lu %Lu %Lu", &user, &nice, &system, &idle, &iowait, &irq, &softirq ) < 7 ) iowait = irq = softirq = 0; used = user + nice + system + irq + softirq; total = used + idle + iowait; cu, Stefan
#664208#25
Date:
2012-08-13 17:17:45 UTC
From:
To:
I had the same problem on an 8-core Intel CPU. The patch that seems to solve
this issue is  slightly different (for i386 (686) arch.):
--- xfce4-cpugraph-plugin-0.4.0/panel-plugin/cpu_os.c.orig      2007-11-22 06:18:52.000000000 +0100
+++ xfce4-cpugraph-plugin-0.4.0/panel-plugin/cpu_os.c   2012-08-13 18:39:41.000000000 +0200
@@ -84,8 +84,8 @@
 cpuLoadData *cpuLoadMon_read(){
        FILE *fStat = NULL;
        char cpuStr[PROCMAXLNLEN];
-       unsigned long user, nice, system, idle;
-       unsigned long used, total;
+       unsigned long long int user, nice, system, idle;
+       unsigned long long int used, total;
        int cpuNr = 0;


@@ -99,7 +99,7 @@
        do
        {
                if(!fgets(cpuStr, PROCMAXLNLEN, fStat)) return(data);
-               sscanf(cpuStr, "%*s %ld %ld %ld %ld", &user, &nice, &system, &idle);
+               sscanf(cpuStr, "%*s %lld %lld %lld %lld", &user, &nice, &system, &idle);

                used = user + nice + system;
                total = used + idle;

Regards,
Zsolt
PS: "multicore" means larger than 2 (or even greater)...
since the plugin works fine on a dual core E2180 Intel CPU @home

#664208#30
Date:
2014-10-07 21:14:32 UTC
From:
To:
Dear Maintainer,

I confirm this bug using an 8-core
Intel(R) Core(TM) i7 CPU         930  @ 2.80GHz
CPU.

I think this bug have been existing still from squeeze... which could be
solved by using "long long int" instead of "long" for vars named
user, nice, systen, idle, used, total

and then replace corresponding %ld with %lld in the sscanf string.

Zsolt