+// Read from ring buffer and dispatch to write plugins
+static int read_ring_buffer() {
+ pthread_mutex_lock(&procevent_lock);
+
+ // If there's currently nothing to read from the buffer,
+ // then wait
+ if (ring.head == ring.tail)
+ pthread_cond_wait(&procevent_cond, &procevent_lock);
+
+ while (ring.head != ring.tail) {
+ int next = ring.tail + 1;
+
+ if (next >= ring.maxLen)
+ next = 0;
+
+ if (ring.buffer[ring.tail][1] == PROCEVENT_EXITED) {
+ processlist_t *pl = process_map_check(ring.buffer[ring.tail][0], NULL);
+
+ if (pl != NULL) {
+ // This process is of interest to us, so publish its EXITED status
+ procevent_dispatch_notification(ring.buffer[ring.tail][0], "gauge",
+ ring.buffer[ring.tail][1], pl->process,
+ ring.buffer[ring.tail][3]);
+ DEBUG(
+ "procevent plugin: PID %ld (%s) EXITED, removing PID from process "
+ "list",
+ pl->pid, pl->process);
+ pl->pid = -1;
+ pl->last_status = -1;
+ }
+ } else if (ring.buffer[ring.tail][1] == PROCEVENT_STARTED) {
+ // a new process has started, so check if we should monitor it
+ processlist_t *pl = process_check(ring.buffer[ring.tail][0]);
+
+ // If we had already seen this process name and pid combo before,
+ // and the last message was a "process started" message, don't send
+ // the notfication again
+
+ if (pl != NULL && pl->last_status != PROCEVENT_STARTED) {
+ // This process is of interest to us, so publish its STARTED status
+ procevent_dispatch_notification(ring.buffer[ring.tail][0], "gauge",
+ ring.buffer[ring.tail][1], pl->process,
+ ring.buffer[ring.tail][3]);
+
+ pl->last_status = PROCEVENT_STARTED;
+
+ DEBUG("procevent plugin: PID %ld (%s) STARTED, adding PID to process "
+ "list",
+ pl->pid, pl->process);
+ }
+ }
+
+ ring.tail = next;
+ }
+
+ pthread_mutex_unlock(&procevent_lock);
+
+ return 0;
+}
+
+// Entry point for thread responsible for listening
+// to netlink socket and writing data to ring buffer
+static void *procevent_netlink_thread(void *arg) /* {{{ */