xdbe replaced with more generic pixmap based buffering but there are 3 major bugs:
[monky] / src / common.c
index 1bad93d..b9b093b 100644 (file)
@@ -84,9 +84,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)
@@ -268,7 +269,7 @@ void format_seconds_short(char *buf, unsigned int n, long seconds)
  * Populated while initialising text objects in construct_text_object(). */
 static struct update_cb {
        struct update_cb *next;
-       void (*func)(void);
+       int (*func)(void);
        pthread_t thread;
        sem_t start_wait, end_wait;
 
@@ -277,14 +278,16 @@ 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. */
-void add_update_callback(void (*func)(void))
+void add_update_callback(int (*func)(void))
 {
        struct update_cb *uc = &update_cb_head;
 
@@ -306,8 +309,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 +326,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 +360,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 +372,18 @@ 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;
-               (*ucb->func)();
-               sem_post(&ucb->end_wait);
+               if (sem_wait(&ucb->start_wait)) pthread_exit(NULL);
+               if (ucb->running == 0) pthread_exit(NULL);
+               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)) pthread_exit(NULL);
        }
 }
 
@@ -395,12 +410,21 @@ 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)
+       for (uc = update_cb_head.next; uc; uc = uc->next) {
                sem_wait(&uc->end_wait);
+               if(uc == uc->next) {
+                       pthread_join(uc->thread, NULL);
+                       free(uc);
+                       exit(EXIT_FAILURE);
+               }
+       }
 
        /* XXX: move the following into the update_meminfo() functions? */
        if (no_buffers) {