From e91e34c7a69864ffcd8dcbe42523645cfbb92d11 Mon Sep 17 00:00:00 2001
From: Brenden Matthews <brenden@diddyinc.com>
Date: Sat, 30 Jan 2010 11:05:55 -0800
Subject: [PATCH] Fix data starvation bug in cpu stats.

---
 src/common.h  |    3 +++
 src/conky.c   |   18 ++++++++++--------
 src/freebsd.c |   10 ++++++++++
 src/linux.c   |   10 ++++++++++
 src/netbsd.c  |   10 ++++++++++
 src/openbsd.c |   10 ++++++++++
 6 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/src/common.h b/src/common.h
index f9f0393..417f34a 100644
--- a/src/common.h
+++ b/src/common.h
@@ -23,6 +23,9 @@ void update_uptime(void);
 void update_meminfo(void);
 void update_net_stats(void);
 void update_cpu_usage(void);
+/* returns 1 if cpu stats are ready, 0 otherwise.  this will block until cpu
+ * stats are available. */
+int cpu_stats_ready(void);
 void update_total_processes(void);
 void update_uname(void);
 void update_threads(void);
diff --git a/src/conky.c b/src/conky.c
index d31698f..e527bc7 100644
--- a/src/conky.c
+++ b/src/conky.c
@@ -898,14 +898,16 @@ void generate_text_internal(char *p, int p_max_size,
 				print_cmdline_to_pid(obj, p, p_max_size);
 			}
 			OBJ(cpu) {
-				if (obj->data.i > info.cpu_count) {
-					NORM_ERR("obj->data.i %i info.cpu_count %i",
-							obj->data.i, info.cpu_count);
-					CRIT_ERR(NULL, NULL, "attempting to use more CPUs than you have!");
-				}
-				if (cur->cpu_usage) {
-				    percent_print(p, p_max_size,
-				              round_to_int(cur->cpu_usage[obj->data.i] * 100.0));
+				if (cpu_stats_ready()) {
+					if (obj->data.i > info.cpu_count) {
+						NORM_ERR("obj->data.i %i info.cpu_count %i",
+								obj->data.i, info.cpu_count);
+						CRIT_ERR(NULL, NULL, "attempting to use more CPUs than you have!");
+					}
+					if (cur->cpu_usage) {
+						percent_print(p, p_max_size,
+								round_to_int(cur->cpu_usage[obj->data.i] * 100.0));
+					}
 				}
 			}
 			OBJ(cpugauge)
diff --git a/src/freebsd.c b/src/freebsd.c
index d79c9c4..3904c80 100644
--- a/src/freebsd.c
+++ b/src/freebsd.c
@@ -314,6 +314,13 @@ void get_cpu_count(void)
 	}
 }
 
+static pthread_mutex_t cpu_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int cpu_stats_ready(void)
+{
+	return pthread_mutex_trylock(&cpu_initialized_mutex) ? 1 : 0;
+}
+
 /* XXX: SMP support */
 void update_cpu_usage(void)
 {
@@ -349,6 +356,9 @@ void update_cpu_usage(void)
 
 	oldused = used;
 	oldtotal = total;
+	
+	/* mark cpu data as initialized */
+	pthread_mutex_trylock(&cpu_initialized_mutex);
 }
 
 void update_load_average(void)
diff --git a/src/linux.c b/src/linux.c
index a229809..21da15d 100644
--- a/src/linux.c
+++ b/src/linux.c
@@ -661,6 +661,13 @@ void get_cpu_count(void)
 #define TMPL_LONGSTAT "%*s %llu %llu %llu %llu %llu %llu %llu %llu"
 #define TMPL_SHORTSTAT "%*s %llu %llu %llu %llu"
 
+static pthread_mutex_t cpu_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int cpu_stats_ready(void)
+{
+	return pthread_mutex_trylock(&cpu_initialized_mutex) ? 1 : 0;
+}
+
 void update_stat(void)
 {
 	FILE *stat_fp;
@@ -782,6 +789,9 @@ void update_stat(void)
 		}
 	}
 	fclose(stat_fp);
+
+	/* mark cpu data as initialized */
+	pthread_mutex_trylock(&cpu_initialized_mutex);
 }
 
 void update_running_processes(void)
diff --git a/src/netbsd.c b/src/netbsd.c
index d1236bb..f27ecc9 100644
--- a/src/netbsd.c
+++ b/src/netbsd.c
@@ -275,6 +275,13 @@ struct cpu_load_struct fresh = {
 
 long cpu_used, oldtotal, oldused;
 
+static pthread_mutex_t cpu_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int cpu_stats_ready(void)
+{
+	return pthread_mutex_trylock(&cpu_initialized_mutex) ? 1 : 0;
+}
+
 void update_cpu_usage()
 {
 	long used, total;
@@ -305,6 +312,9 @@ void update_cpu_usage()
 
 	oldused = used;
 	oldtotal = total;
+	
+	/* mark cpu data as initialized */
+	pthread_mutex_trylock(&cpu_initialized_mutex);
 }
 
 void update_load_average()
diff --git a/src/openbsd.c b/src/openbsd.c
index 2cd3f0c..50a619b 100644
--- a/src/openbsd.c
+++ b/src/openbsd.c
@@ -343,6 +343,13 @@ void get_cpu_count()
 #endif
 }
 
+static pthread_mutex_t cpu_initialized_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+int cpu_stats_ready(void)
+{
+	return pthread_mutex_trylock(&cpu_initialized_mutex) ? 1 : 0;
+}
+
 void update_cpu_usage()
 {
 #ifdef OLDCPU
@@ -427,6 +434,9 @@ void update_cpu_usage()
 		oldtotal[i] = total;
 	}
 #endif
+	
+	/* mark cpu data as initialized */
+	pthread_mutex_trylock(&cpu_initialized_mutex);
 }
 
 void update_load_average()
-- 
1.6.6.1


