1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2025-01-13 19:22:58 +00:00

Bugfix: memory and thread-deleting problems

For example the following config had a problem:
TEXT
$i8k_cpu_temp

I could fix it shorter, but then valgrind would still show memleaks
This commit is contained in:
Nikolas Garofil 2010-05-05 18:46:04 +02:00
parent 3f7ecb3a26
commit a32d9e41a4
29 changed files with 132 additions and 82 deletions

View File

@ -180,7 +180,7 @@ static int fill_items(int sock, PAPCUPSD_S apc)
//
// Conky update function for apcupsd data
//
void update_apcupsd(void)
int update_apcupsd(void)
{
int i;
APCUPSD_S apc;
@ -251,7 +251,7 @@ void update_apcupsd(void)
// "atomically" copy the data into working set
//
memcpy(apcupsd.items, apc.items, sizeof(apcupsd.items));
return;
return 0;
}
int apcupsd_scan_arg(const char *arg)

View File

@ -28,7 +28,7 @@
int apcupsd_scan_arg(const char *);
/* Service routine for the conky main thread */
void update_apcupsd(void);
int update_apcupsd(void);
double apcupsd_loadbarval(struct text_object *);

View File

@ -87,9 +87,10 @@ char *strndup(const char *s, size_t n)
}
#endif /* HAVE_STRNDUP */
void update_uname(void)
int update_uname(void)
{
uname(&info.uname_s);
return 0;
}
double get_time(void)
@ -261,7 +262,7 @@ void format_seconds_short(char *buf, unsigned int n, long seconds)
* Populated while initialising text objects in construct_text_object(). */
struct update_cb {
struct update_cb *next;
void (*func)(void);
int (*func)(void);
pthread_t thread;
sem_t start_wait, end_wait;
update_cb() : next(NULL), func(NULL) {}
@ -279,7 +280,7 @@ static int threading_started = 0;
/* Register an update callback. Don't allow duplicates, to minimise side
* effects and overhead. */
void add_update_callback(void (*func)(void))
void add_update_callback(int (*func)(void))
{
struct update_cb *uc = &update_cb_head;
@ -369,7 +370,12 @@ static void *run_update_callback(void *data)
while (1) {
if (sem_wait(&ucb->start_wait)) return(NULL);
if (ucb->running == 0) return(NULL);
(*ucb->func)();
if((*ucb->func)()) {
ucb->next = ucb; //this is normally not be possible, so we use it to show that there was a critical error
sem_post(&ucb->end_wait);
sem_post(&ucb->end_wait);
pthread_exit(NULL);
}
if (sem_post(&ucb->end_wait)) return(NULL);
}
}
@ -404,8 +410,14 @@ void update_stuff(void)
}
/* need to synchronise here, otherwise locking is needed (as data
* would be printed with some update callbacks still running) */
for (uc = update_cb_head.next; uc; uc = uc->next)
for (uc = update_cb_head.next; uc; uc = uc->next) {
sem_wait(&uc->end_wait);
if(uc == uc->next) {
pthread_join(uc->thread, NULL);
delete uc;
exit(EXIT_FAILURE);
}
}
/* XXX: move the following into the update_meminfo() functions? */
if (no_buffers) {

View File

@ -37,27 +37,27 @@ char* readfile(const char* filename, int* total_read, char showerror);
void print_to_bytes(struct text_object *, char *, int);
void add_update_callback(void (*func)(void));
void add_update_callback(int (*func)(void));
void free_update_callbacks(void);
void start_update_threading(void);
void strfold(char *start, int count);
int check_mount(struct text_object *);
void prepare_update(void);
void update_uptime(void);
void update_meminfo(void);
void update_net_stats(void);
void update_cpu_usage(void);
void update_total_processes(void);
void update_uname(void);
void update_threads(void);
void update_running_processes(void);
int update_uptime(void);
int update_meminfo(void);
int update_net_stats(void);
int update_cpu_usage(void);
int update_total_processes(void);
int update_uname(void);
int update_threads(void);
int update_running_processes(void);
void update_stuff(void);
char get_freq(char *, size_t, const char *, int, unsigned int);
void print_voltage_mv(struct text_object *, char *, int);
void print_voltage_v(struct text_object *, char *, int);
void update_load_average(void);
void update_top(void);
int update_load_average(void);
int update_top(void);
void free_all_processes(void);
struct process *get_first_process(void);
void get_cpu_count(void);

View File

@ -490,6 +490,7 @@ static inline void for_each_line(char *b, int f(char *, int))
char *ps, *pe;
int special_index = 0; /* specials index */
if(! b) return;
for (ps = b, pe = b; *pe; pe++) {
if (*pe == '\n') {
*pe = '\0';
@ -748,6 +749,9 @@ void generate_text_internal(char *p, int p_max_size, struct text_object root)
{
struct text_object *obj;
size_t a;
if(! p) return;
#ifdef BUILD_ICONV
char *buff_in;
@ -2427,9 +2431,7 @@ void free_specials(special_t *current) {
}
}
void clean_up(void *memtofree1, void* memtofree2)
{
free_update_callbacks();
void clean_up_without_threads(void *memtofree1, void* memtofree2) {
#ifdef BUILD_NCURSES
if(output_methods & TO_NCURSES) {
@ -2501,6 +2503,12 @@ void clean_up(void *memtofree1, void* memtofree2)
free_and_zero(global_cpu);
}
void clean_up(void *memtofree1, void* memtofree2)
{
free_update_callbacks();
clean_up_without_threads(memtofree1, memtofree2);
}
static bool string_to_bool(const char *s)
{
if (!s) {

View File

@ -63,7 +63,7 @@ struct diskio_stat {
extern struct diskio_stat stats;
struct diskio_stat *prepare_diskio_stat(const char *);
void update_diskio(void);
int update_diskio(void);
void clear_diskio_stats(void);
void update_diskio_values(struct diskio_stat *, unsigned int, unsigned int);

View File

@ -49,10 +49,11 @@ struct _entropy {
static _entropy entropy;
void update_entropy(void)
int update_entropy(void)
{
get_entropy_avail(&entropy.avail);
get_entropy_poolsize(&entropy.poolsize);
return 0;
}
void print_entropy_avail(struct text_object *obj, char *p, int p_max_size)

View File

@ -31,7 +31,7 @@
#ifndef _ENTROPY_H
#define _ENTROPY_H
void update_entropy(void);
int update_entropy(void);
void print_entropy_avail(struct text_object *, char *, int);
uint8_t entropy_percentage(struct text_object *);

View File

@ -69,13 +69,13 @@ static void update_fs_stat(struct fs_stat *fs);
void get_fs_type(const char *path, char *result);
void update_fs_stats(void)
int update_fs_stats(void)
{
unsigned i;
static double last_fs_update = 0.0;
if (current_update_time - last_fs_update < 13)
return;
return 0;
for (i = 0; i < MAX_FS_STATS; ++i) {
if (fs_stats[i].set) {
@ -83,6 +83,7 @@ void update_fs_stats(void)
}
}
last_fs_update = current_update_time;
return 0;
}
void clear_fs_stats(void)

View File

@ -58,7 +58,7 @@ void print_fs_size(struct text_object *, char *, int);
void print_fs_used(struct text_object *, char *, int);
void print_fs_type(struct text_object *, char *, int);
void update_fs_stats(void);
int update_fs_stats(void);
struct fs_stat *prepare_fs_stat(const char *path);
void clear_fs_stats(void);

View File

@ -207,29 +207,30 @@ out_fail:
return 1;
}
void update_hddtemp(void) {
int update_hddtemp(void) {
char *data, *dev, unit, *saveptr;
short val;
static double last_hddtemp_update = 0.0;
/* limit tcp connection overhead */
if (current_update_time - last_hddtemp_update < 5)
return;
return 0;
last_hddtemp_update = current_update_time;
free_hddtemp_info();
if (!(data = fetch_hddtemp_output()))
return;
return 0;
if (read_hdd_val(data, &dev, &val, &unit, &saveptr)) {
free(data);
return;
return 0;
}
do {
add_hddtemp_info(dev, val, unit);
} while (!read_hdd_val(NULL, &dev, &val, &unit, &saveptr));
free(data);
return 0;
}
void free_hddtemp(struct text_object *obj)

View File

@ -29,7 +29,7 @@
void set_hddtemp_host(const char *);
void set_hddtemp_port(const char *);
void update_hddtemp(void);
int update_hddtemp(void);
void free_hddtemp(struct text_object *);
void print_hddtemp(struct text_object *, char *, int);

View File

@ -53,7 +53,7 @@ struct _i8k {
#define PROC_I8K "/proc/i8k"
#define I8K_DELIM " "
static char *i8k_procbuf = NULL;
void update_i8k(void)
int update_i8k(void)
{
FILE *fp;
@ -61,8 +61,13 @@ void update_i8k(void)
i8k_procbuf = (char *) malloc(128 * sizeof(char));
}
if ((fp = fopen(PROC_I8K, "r")) == NULL) {
CRIT_ERR(NULL, NULL, "/proc/i8k doesn't exist! use insmod to make sure the kernel "
"driver is loaded...");
free_and_zero(i8k_procbuf);
/*THREAD_CRIT_ERR(NULL, NULL, "/proc/i8k doesn't exist! use insmod to make sure the kernel "
"driver is loaded...");*/
NORM_ERR("/proc/i8k doesn't exist! use insmod to make sure the kernel driver is loaded...");
clean_up_without_threads(NULL, NULL);
free(current_mail_spool);
return 1;
}
memset(&i8k_procbuf[0], 0, 128);
@ -82,6 +87,7 @@ void update_i8k(void)
i8k.right_fan_rpm = strtok(NULL, I8K_DELIM);
i8k.ac_status = strtok(NULL, I8K_DELIM);
i8k.buttons_status = strtok(NULL, I8K_DELIM);
return 0;
}
static const char *fan_status_to_string(int status)

View File

@ -32,7 +32,7 @@
#ifndef _I8K_H
#define _I8K_H
void update_i8k(void);
int update_i8k(void);
void print_i8k_left_fan_status(struct text_object *, char *, int);
void print_i8k_cpu_temp(struct text_object *, char *, int);
void print_i8k_right_fan_status(struct text_object *, char *, int);

View File

@ -129,7 +129,7 @@ void get_ibm_acpi_fan(struct text_object *obj, char *p, int p_max_size)
temperatures: 41 43 31 46 33 -128 29 -128
* Peter Tarjan (ptarjan@citromail.hu) */
void get_ibm_acpi_temps(void)
int get_ibm_acpi_temps(void)
{
FILE *fp;
@ -158,6 +158,7 @@ void get_ibm_acpi_temps(void)
}
fclose(fp);
return 0;
}
/* get volume (0-14) on IBM/Lenovo laptops running the ibm acpi.

View File

@ -27,7 +27,7 @@
#define _IBM_H
void get_ibm_acpi_fan(struct text_object *, char *, int);
void get_ibm_acpi_temps(void);
int get_ibm_acpi_temps(void);
void get_ibm_acpi_volume(struct text_object *, char *, int);
void get_ibm_acpi_brightness(struct text_object *, char *, int);

View File

@ -101,7 +101,7 @@ void prepare_update(void)
{
}
void update_uptime(void)
int update_uptime(void)
{
#ifdef HAVE_SYSINFO
if (!prefer_proc) {
@ -117,12 +117,13 @@ void update_uptime(void)
if (!(fp = open_file("/proc/uptime", &rep))) {
info.uptime = 0.0;
return;
return 0;
}
if (fscanf(fp, "%lf", &info.uptime) <= 0)
info.uptime = 0;
fclose(fp);
}
return 0;
}
int check_mount(struct text_object *obj)
@ -153,7 +154,7 @@ int check_mount(struct text_object *obj)
/* these things are also in sysinfo except Buffers:
* (that's why I'm reading them from proc) */
void update_meminfo(void)
int update_meminfo(void)
{
FILE *meminfo_fp;
static int rep = 0;
@ -165,7 +166,7 @@ void update_meminfo(void)
info.bufmem = info.buffers = info.cached = info.memfree = info.memeasyfree = 0;
if (!(meminfo_fp = open_file("/proc/meminfo", &rep))) {
return;
return 0;
}
while (!feof(meminfo_fp)) {
@ -195,6 +196,7 @@ void update_meminfo(void)
info.bufmem = info.cached + info.buffers;
fclose(meminfo_fp);
return 0;
}
void print_laptop_mode(struct text_object *obj, char *p, int p_max_size)
@ -270,7 +272,7 @@ void update_gateway_info_failure(const char *reason)
/* Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT */
#define RT_ENTRY_FORMAT "%63s %lx %lx %x %*d %*d %*d %lx %*d %*d %*d\n"
void update_gateway_info(void)
int update_gateway_info(void)
{
FILE *fp;
struct in_addr ina;
@ -284,13 +286,13 @@ void update_gateway_info(void)
if ((fp = fopen("/proc/net/route", "r")) == NULL) {
update_gateway_info_failure("fopen()");
return;
return 0;
}
/* skip over the table header line, which is always present */
if (fscanf(fp, "%*[^\n]\n") < 0) {
fclose(fp);
return;
return 0;
}
while (!feof(fp)) {
@ -307,7 +309,7 @@ void update_gateway_info(void)
}
}
fclose(fp);
return;
return 0;
}
void free_gateway_info(struct text_object *obj)
@ -339,7 +341,7 @@ void print_gateway_ip(struct text_object *obj, char *p, int p_max_size)
snprintf(p, p_max_size, "%s", gw_info.ip);
}
void update_net_stats(void)
int update_net_stats(void)
{
FILE *net_dev_fp;
static int rep = 0;
@ -363,19 +365,19 @@ void update_net_stats(void)
/* get delta */
delta = current_update_time - last_update_time;
if (delta <= 0.0001) {
return;
return 0;
}
/* open file and ignore first two lines */
if (!(net_dev_fp = open_file("/proc/net/dev", &rep))) {
clear_net_stats();
return;
return 0;
}
if (!fgets(buf, 255, net_dev_fp) || /* garbage */
!fgets(buf, 255, net_dev_fp)) { /* garbage (field names) */
fclose(net_dev_fp);
return;
return 0;
}
/* read each interface */
@ -554,11 +556,12 @@ void update_net_stats(void)
first = 0;
fclose(net_dev_fp);
return 0;
}
int result;
void update_total_processes(void)
int update_total_processes(void)
{
DIR *dir;
struct dirent *entry;
@ -567,23 +570,24 @@ void update_total_processes(void)
info.procs = 0;
if (!(dir = opendir("/proc"))) {
return;
return 0;
}
while ((entry = readdir(dir))) {
if (!entry) {
/* Problem reading list of processes */
closedir(dir);
info.procs = 0;
return;
return 0;
}
if (sscanf(entry->d_name, "%d%c", &ignore1, &ignore2) == 1) {
info.procs++;
}
}
closedir(dir);
return 0;
}
void update_threads(void)
int update_threads(void)
{
#ifdef HAVE_SYSINFO
if (!prefer_proc) {
@ -599,12 +603,13 @@ void update_threads(void)
if (!(fp = open_file("/proc/loadavg", &rep))) {
info.threads = 0;
return;
return 0;
}
if (fscanf(fp, "%*f %*f %*f %*d/%hu", &info.threads) <= 0)
info.threads = 0;
fclose(fp);
}
return 0;
}
#define CPU_SAMPLE_COUNT 15
@ -678,7 +683,7 @@ 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"
void update_stat(void)
int update_stat(void)
{
FILE *stat_fp;
static int rep = 0;
@ -700,7 +705,7 @@ void update_stat(void)
pthread_mutex_lock(&last_stat_update_mutex);
if (last_stat_update == current_update_time) {
pthread_mutex_unlock(&last_stat_update_mutex);
return;
return 0;
}
last_stat_update = current_update_time;
pthread_mutex_unlock(&last_stat_update_mutex);
@ -728,7 +733,7 @@ void update_stat(void)
if (info.cpu_usage) {
memset(info.cpu_usage, 0, info.cpu_count * sizeof(float));
}
return;
return 0;
}
idx = 0;
@ -799,19 +804,22 @@ void update_stat(void)
}
}
fclose(stat_fp);
return 0;
}
void update_running_processes(void)
int update_running_processes(void)
{
update_stat();
return 0;
}
void update_cpu_usage(void)
int update_cpu_usage(void)
{
update_stat();
return 0;
}
void update_load_average(void)
int update_load_average(void)
{
#ifdef HAVE_GETLOADAVG
if (!prefer_proc) {
@ -829,13 +837,14 @@ void update_load_average(void)
if (!(fp = open_file("/proc/loadavg", &rep))) {
info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0;
return;
return 0;
}
if (fscanf(fp, "%f %f %f", &info.loadavg[0], &info.loadavg[1],
&info.loadavg[2]) < 0)
info.loadavg[0] = info.loadavg[1] = info.loadavg[2] = 0.0;
fclose(fp);
}
return 0;
}
/***********************************************************/
@ -2209,7 +2218,7 @@ void get_powerbook_batt_info(struct text_object *obj, char *buffer, int n)
snprintf(buffer, n, "%s", pb_battery_info[obj->data.i]);
}
void update_top(void)
int update_top(void)
{
process_find_top(info.cpu, info.memu, info.time
#ifdef BUILD_IOSTATS
@ -2217,6 +2226,7 @@ void update_top(void)
#endif
);
info.first_process = get_first_process();
return 0;
}
#define ENTROPY_AVAIL_PATH "/proc/sys/kernel/random/entropy_avail"
@ -2319,7 +2329,7 @@ int is_disk(char *dev)
return dev_cur->memoized;
}
void update_diskio(void)
int update_diskio(void)
{
FILE *fp;
static int rep = 0;
@ -2335,7 +2345,7 @@ void update_diskio(void)
stats.current_write = 0;
if (!(fp = open_file("/proc/diskstats", &rep))) {
return;
return 0;
}
/* read reads and writes from all disks (minor = 0), including cd-roms
@ -2370,6 +2380,7 @@ void update_diskio(void)
}
update_diskio_values(&stats, total_reads, total_writes);
fclose(fp);
return 0;
}
void print_distribution(struct text_object *obj, char *p, int p_max_size)

View File

@ -33,7 +33,7 @@ void print_disk_protect_queue(struct text_object *, char *, int);
void print_ioscheduler(struct text_object *, char *, int);
void print_laptop_mode(struct text_object *, char *, int);
void update_gateway_info(void);
int update_gateway_info(void);
void free_gateway_info(struct text_object *obj);
int gateway_exists(struct text_object *);
void print_gateway_iface(struct text_object *, char *, int);
@ -51,7 +51,7 @@ void free_sysfs_sensor(struct text_object *);
int get_entropy_avail(unsigned int *);
int get_entropy_poolsize(unsigned int *);
void update_stat(void);
int update_stat(void);
void print_distribution(struct text_object *, char *, int);

View File

@ -34,6 +34,7 @@
#include "mail.h"
void clean_up(void *memtofree1, void* memtofree2);
void clean_up_without_threads(void *memtofree1, void* memtofree2);
#define NORM_ERR(...) { \
fprintf(stderr, PACKAGE_NAME": "); \
@ -45,6 +46,9 @@ void clean_up(void *memtofree1, void* memtofree2);
#define CRIT_ERR(memtofree1, memtofree2, ...) \
{ NORM_ERR(__VA_ARGS__); clean_up(memtofree1, memtofree2); free(current_mail_spool); exit(EXIT_FAILURE); }
#define THREAD_CRIT_ERR(memtofree1, memtofree2, ...) \
{ NORM_ERR(__VA_ARGS__); clean_up_without_threads(memtofree1, memtofree2); free(current_mail_spool); return; }
/* debugging output */
extern int global_debug_level;
#define __DBGP(level, ...) \

View File

@ -139,9 +139,10 @@ static int run_moc_thread(double interval)
return 0;
}
void update_moc(void)
int update_moc(void)
{
run_moc_thread(info.music_player_interval * 100000);
return 0;
}
#define MOC_PRINT_GENERATOR(type, alt) \

View File

@ -24,7 +24,7 @@
#ifndef MOC_H_
#define MOC_H_
void update_moc(void);
int update_moc(void);
void free_moc(struct text_object *);
void print_moc_state(struct text_object *, char *, int);

View File

@ -125,20 +125,21 @@ void free_mpd(struct text_object *obj)
static void update_mpd_thread(thread_handle &handle);
void update_mpd(void)
int update_mpd(void)
{
int interval;
static timed_thread_ptr thread;
if (thread)
return;
return 0;
interval = info.music_player_interval * 1000000;
thread = timed_thread::create(std::bind(update_mpd_thread, std::placeholders::_1), interval);
if (!thread) {
NORM_ERR("Failed to create MPD timed thread");
return;
return 0;
}
return 0;
}
/* stringMAXdup dups at most text_buffer_size bytes */

View File

@ -35,7 +35,7 @@ int mpd_set_port(const char *);
/* text object functions */
void init_mpd(void);
void free_mpd(struct text_object *);
void update_mpd(void);
int update_mpd(void);
void print_mpd_elapsed(struct text_object *, char *, int);
void print_mpd_length(struct text_object *, char *, int);

View File

@ -396,7 +396,7 @@ void free_dns_data(struct text_object *obj)
memset(&dns_data, 0, sizeof(dns_data));
}
void update_dns_data(void)
int update_dns_data(void)
{
FILE *fp;
char line[256];
@ -404,7 +404,7 @@ void update_dns_data(void)
/* maybe updating too often causes higher load because of /etc lying on a real FS
if (current_update_time - last_dns_update < 10.0)
return;
return 0;
last_dns_update = current_update_time;
*/
@ -412,7 +412,7 @@ void update_dns_data(void)
free_dns_data(NULL);
if ((fp = fopen("/etc/resolv.conf", "r")) == NULL)
return;
return 0;
while(!feof(fp)) {
if (fgets(line, 255, fp) == NULL) {
break;
@ -425,6 +425,7 @@ void update_dns_data(void)
}
}
fclose(fp);
return 0;
}
void parse_nameserver_arg(struct text_object *obj, const char *arg)

View File

@ -92,7 +92,7 @@ int interface_up(struct text_object *);
void free_if_up(struct text_object *);
void free_dns_data(struct text_object *);
void update_dns_data(void);
int update_dns_data(void);
void parse_nameserver_arg(struct text_object *, const char *);
void print_nameserver(struct text_object *, char *, int);

View File

@ -131,9 +131,10 @@ void tcp_portmon_action(struct text_object *obj, char *p, int p_max_size)
}
}
void tcp_portmon_update(void)
int tcp_portmon_update(void)
{
update_tcp_port_monitor_collection(pmc);
return 0;
}
int tcp_portmon_clear(void)

View File

@ -39,7 +39,7 @@ struct text_object;
int tcp_portmon_init(struct text_object *, const char *);
void tcp_portmon_action(struct text_object *, char *, int);
void tcp_portmon_update(void);
int tcp_portmon_update(void);
int tcp_portmon_clear(void);
int tcp_portmon_set_max_connections(int);
void tcp_portmon_free(struct text_object *);

View File

@ -151,7 +151,7 @@ static void update_user_time(char *tty)
}
}
void update_users(void)
int update_users(void)
{
struct information *current_info = &info;
char temp[BUFLEN] = "";
@ -197,6 +197,7 @@ void update_users(void)
current_info->users.times = (char*)malloc(text_buffer_size);
strncpy(current_info->users.times, "broken", text_buffer_size);
}
return 0;
}
void print_user_names(struct text_object *obj, char *p, int p_max_size)

View File

@ -31,7 +31,7 @@
#ifndef _USERS_H
#define _USERS_H
void update_users(void);
int update_users(void);
void print_user_names(struct text_object *, char *, int);
void print_user_terms(struct text_object *, char *, int);