}
#endif /* HAVE_STRNDUP */
-void update_uname(void)
+int update_uname(void)
{
uname(&info.uname_s);
+ return 0;
}
double get_time(void)
* 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;
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;
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);
+ }
}
}
/* 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 */
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);
+ }
}
}
{
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);
}
}
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) {