Added disable_auto_reload option, callback fixes.
authorBrenden Matthews <brenden@diddyinc.com>
Sat, 2 Jan 2010 21:31:09 +0000 (13:31 -0800)
committerBrenden Matthews <brenden@diddyinc.com>
Sat, 2 Jan 2010 21:33:17 +0000 (13:33 -0800)
There were some issues with reloading and the threaded callback
framework, which I think are mostly resolved now, but may need more
testing.

doc/config_settings.xml
src/common.c
src/conky.c

index a12a77d..ef86824 100644 (file)
     <varlistentry>
         <term>
             <command>
+                <option>disable_auto_reload</option>
+            </command>
+        </term>
+               <listitem>Enable to disable the inotify-based auto config reload feature.
+        <para /></listitem>
+    </varlistentry>
+    <varlistentry>
+        <term>
+            <command>
                 <option>diskio_avg_samples</option>
             </command>
         </term>
index 1bad93d..4a8d78a 100644 (file)
@@ -277,10 +277,12 @@ static struct update_cb {
        volatile char running;
 } update_cb_head = {
        .next = NULL,
+       .func = NULL,
 };
 
-static void *run_update_callback(void *);
-static int threading_started;
+static void *run_update_callback(void *) __attribute__((noreturn));
+
+static int threading_started = 0;
 
 /* Register an update callback. Don't allow duplicates, to minimise side
  * effects and overhead. */
@@ -306,8 +308,10 @@ void add_update_callback(void (*func)(void))
        sem_init(&uc->end_wait, 0, 0);
 
        if (threading_started) {
-               uc->running = 1;
-               pthread_create(&uc->thread, NULL, &run_update_callback, uc);
+               if (!uc->running) {
+                       uc->running = 1;
+                       pthread_create(&uc->thread, NULL, &run_update_callback, uc);
+               }
        }
 }
 
@@ -321,7 +325,9 @@ static void __free_update_callbacks(struct update_cb *uc)
                /* send cancellation request, then trigger and join the thread */
                uc->running = 0;
                sem_post(&uc->start_wait);
-               pthread_join(uc->thread, NULL);
+       }
+       if (pthread_join(uc->thread, NULL)) {
+               NORM_ERR("Error destroying thread");
        }
 
        /* finally destroy the semaphores */
@@ -353,9 +359,11 @@ void start_update_threading(void)
 
        threading_started = 1;
 
-       for(uc = update_cb_head.next; uc; uc = uc->next) {
-               uc->running = 1;
-               pthread_create(&uc->thread, NULL, &run_update_callback, uc);
+       for (uc = update_cb_head.next; uc; uc = uc->next) {
+               if (!uc->running) {
+                       uc->running = 1;
+                       pthread_create(&uc->thread, NULL, &run_update_callback, uc);
+               }
        }
 }
 
@@ -363,12 +371,13 @@ static void *run_update_callback(void *data)
 {
        struct update_cb *ucb = data;
 
+       if (!ucb || !ucb->func) pthread_exit(NULL);
+
        while (1) {
-               sem_wait(&ucb->start_wait);
-               if (ucb->running == 0)
-                       return NULL;
+               if (sem_wait(&ucb->start_wait)) pthread_exit(NULL);
+               if (ucb->running == 0) pthread_exit(NULL);
                (*ucb->func)();
-               sem_post(&ucb->end_wait);
+               if (sem_post(&ucb->end_wait)) pthread_exit(NULL);
        }
 }
 
@@ -395,8 +404,11 @@ void update_stuff(void)
 
        prepare_update();
 
-       for (uc = update_cb_head.next; uc; uc = uc->next)
-               sem_post(&uc->start_wait);
+       for (uc = update_cb_head.next; uc; uc = uc->next) {
+               if (sem_post(&uc->start_wait)) {
+                       NORM_ERR("Semaphore error");
+               }
+       }
        /* 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)
index a7fa5d2..18224f9 100644 (file)
@@ -147,6 +147,9 @@ char *get_apm_battery_time(void);
 /* debugging level, used by logging.h */
 int global_debug_level = 0;
 
+/* disable inotify auto reload feature if desired */
+int disable_auto_reload = 0;
+
 /* two strings for internal use */
 static char *tmpstring1, *tmpstring2;
 
@@ -462,7 +465,7 @@ int check_contains(char *f, char *s)
 
 #define SECRIT_MULTILINE_CHAR '\x02'
 
-static inline int calc_text_width(const char *s)
+int calc_text_width(const char *s)
 {
        size_t slen = strlen(s);
 
@@ -2466,7 +2469,7 @@ void set_update_interval(double interval)
        update_interval_old = interval;
 }
 
-static inline int get_string_width(const char *s)
+int get_string_width(const char *s)
 {
        return *s ? calc_text_width(s) : 0;
 }
@@ -3884,12 +3887,12 @@ static void main_loop(void)
                                break;
                }
 #ifdef HAVE_SYS_INOTIFY_H
-               if (inotify_fd != -1 && inotify_config_wd == -1 && current_config != 0) {
+               if (!disable_auto_reload && inotify_fd != -1 && inotify_config_wd == -1 && current_config != 0) {
                        inotify_config_wd = inotify_add_watch(inotify_fd,
                                        current_config,
                                        IN_MODIFY);
                }
-               if (inotify_fd != -1 && inotify_config_wd != -1 && current_config != 0) {
+               if (!disable_auto_reload && inotify_fd != -1 && inotify_config_wd != -1 && current_config != 0) {
                        int len = 0, idx = 0;
                        fd_set descriptors;
                        struct timeval time_to_wait;
@@ -3925,6 +3928,10 @@ static void main_loop(void)
                                        idx += INOTIFY_EVENT_SIZE + ev->len;
                                }
                        }
+               } else if (disable_auto_reload && inotify_fd != -1) {
+                       inotify_rm_watch(inotify_fd, inotify_config_wd);
+                       close(inotify_fd);
+                       inotify_fd = inotify_config_wd = 0;
                }
 #endif /* HAVE_SYS_INOTIFY_H */
 
@@ -3954,6 +3961,7 @@ static void reload_config(void)
 {
        char *current_config_copy = strdup(current_config);
        clean_up(NULL, NULL);
+       sleep(1); /* slight pause */
        current_config = current_config_copy;
        initialisation(argc_copy, argv_copy);
 }
@@ -3962,6 +3970,8 @@ void clean_up(void *memtofree1, void* memtofree2)
 {
        int i;
 
+       free_update_callbacks();
+
 #ifdef NCURSES
        if(output_methods & TO_NCURSES) {
                endwin();
@@ -4013,8 +4023,6 @@ void clean_up(void *memtofree1, void* memtofree2)
 
 #endif /* X11 */
 
-       free_update_callbacks();
-
        free_templates();
 
        free_text_objects(&global_root_object, 0);
@@ -4773,6 +4781,9 @@ char load_config_file(const char *f)
                CONF("extra_newline") {
                        extra_newline = string_to_bool(value);
                }
+               CONF("disable_auto_reload") {
+                       disable_auto_reload = string_to_bool(value);
+               }
                CONF("out_to_stderr") {
                        if(string_to_bool(value))
                                output_methods |= TO_STDERR;