return (0);
}
+static _Bool timeout_reached(struct timespec timeout)
+{
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ return (now.tv_sec >= timeout.tv_sec && now.tv_usec >= (timeout.tv_nsec / 1000));
+}
+
static void *plugin_read_thread (void __attribute__((unused)) *args)
{
while (read_loop != 0)
struct timeval now;
int status;
int rf_type;
+ int rc;
/* Get the read function that needs to be read next. */
rf = c_head_get_root (read_heap);
/* sleep until this entry is due,
* using pthread_cond_timedwait */
pthread_mutex_lock (&read_lock);
- pthread_cond_timedwait (&read_cond, &read_lock,
+ /* In pthread_cond_timedwait, spurious wakeups are possible
+ * (and really happen, at least on NetBSD with > 1 CPU), thus
+ * we need to re-evaluate the condition every time
+ * pthread_cond_timedwait returns. */
+ rc = 0;
+ while (!timeout_reached(rf->rf_next_read) && rc == 0) {
+ rc = pthread_cond_timedwait (&read_cond, &read_lock,
&rf->rf_next_read);
+ }
+
/* Must hold `real_lock' when accessing `rf->rf_type'. */
rf_type = rf->rf_type;
pthread_mutex_unlock (&read_lock);
}
le = llist_search (read_list, name);
+ if (le == NULL)
+ {
+ pthread_mutex_unlock (&read_lock);
+ WARNING ("plugin_unregister_read: No such read function: %s",
+ name);
+ return (-ENOENT);
+ }
+
llist_remove (read_list, le);
rf = le->value;
(*callback) ();
}
- destroy_all_callbacks (&list_write);
+ /* Write plugins which use the `user_data' pointer usually need the
+ * same data available to the flush callback. If this is the case, set
+ * the free_function to NULL when registering the flush callback and to
+ * the real free function when registering the write callback. This way
+ * the data isn't freed twice. */
destroy_all_callbacks (&list_flush);
+ destroy_all_callbacks (&list_write);
+
destroy_all_callbacks (&list_notification);
destroy_all_callbacks (&list_shutdown);
destroy_all_callbacks (&list_log);
va_list ap;
llentry_t *le;
- if (list_log == NULL)
- return;
-
#if !COLLECT_DEBUG
if (level >= LOG_DEBUG)
return;
msg[sizeof (msg) - 1] = '\0';
va_end (ap);
+ if (list_log == NULL)
+ {
+ fprintf (stderr, "%s\n", msg);
+ return;
+ }
+
le = llist_head (list_log);
while (le != NULL)
{