+ pthread_mutex_unlock(&procevent_thread_lock);
+
+ int status = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), recv_flags);
+
+ if (status == 0) {
+ return 0;
+ } else if (status < 0) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ pthread_mutex_lock(&procevent_data_lock);
+
+ // There was nothing more to receive for now, so...
+ // If ring head does not equal ring tail, there is data
+ // in the ring buffer for the dequeue thread to read, so
+ // signal it
+ if (ring.head != ring.tail)
+ pthread_cond_signal(&procevent_cond);
+
+ pthread_mutex_unlock(&procevent_data_lock);
+
+ // Since there was nothing to receive, set recv to block and
+ // try again
+ recv_flags = 0;
+ continue;
+ } else if (errno != EINTR) {
+ ERROR("procevent plugin: socket receive error: %d", errno);
+ return -1;
+ } else {
+ // Interrupt, so just return
+ return 0;
+ }
+ }
+
+ // We successfully received a message, so don't block on the next
+ // read in case there are more (and if there aren't, it will be
+ // handled above in the error-checking)
+ recv_flags = MSG_DONTWAIT;
+
+ int proc_id = -1;
+ int proc_status = -1;
+ int proc_extra = -1;
+
+ switch (nlcn_msg.proc_ev.what) {
+ case PROC_EVENT_NONE:
+ case PROC_EVENT_FORK:
+ case PROC_EVENT_UID:
+ case PROC_EVENT_GID:
+ // Not of interest in current version
+ break;
+ case PROC_EVENT_EXEC:
+ proc_status = PROCEVENT_STARTED;
+ proc_id = nlcn_msg.proc_ev.event_data.exec.process_pid;
+ break;
+ case PROC_EVENT_EXIT:
+ proc_id = nlcn_msg.proc_ev.event_data.exit.process_pid;
+ proc_status = PROCEVENT_EXITED;
+ proc_extra = nlcn_msg.proc_ev.event_data.exit.exit_code;
+ break;
+ default:
+ break;
+ }
+
+ // If we're interested in this process status event, place the event
+ // in the ring buffer for consumption by the main polling thread.
+
+ if (proc_status != -1) {
+ pthread_mutex_lock(&procevent_data_lock);
+
+ int next = ring.head + 1;
+ if (next >= ring.maxLen)
+ next = 0;
+
+ if (next == ring.tail) {
+ // Buffer is full, signal the dequeue thread to process the buffer
+ // and clean it out, and then sleep
+ WARNING("procevent plugin: ring buffer full");
+
+ pthread_cond_signal(&procevent_cond);
+ pthread_mutex_unlock(&procevent_data_lock);
+
+ usleep(1000);
+ continue;
+ } else {
+ DEBUG("procevent plugin: Process %d status is now %s at %llu", proc_id,
+ (proc_status == PROCEVENT_EXITED ? "EXITED" : "STARTED"),
+ (long long unsigned int)CDTIME_T_TO_US(cdtime()));
+
+ if (proc_status == PROCEVENT_EXITED) {
+ ring.buffer[ring.head][0] = proc_id;
+ ring.buffer[ring.head][1] = proc_status;
+ ring.buffer[ring.head][2] = proc_extra;
+ ring.buffer[ring.head][3] =
+ (long long unsigned int)CDTIME_T_TO_US(cdtime());
+ } else {
+ ring.buffer[ring.head][0] = proc_id;
+ ring.buffer[ring.head][1] = proc_status;
+ ring.buffer[ring.head][2] = 0;
+ ring.buffer[ring.head][3] =
+ (long long unsigned int)CDTIME_T_TO_US(cdtime());
+ }
+
+ ring.head = next;
+ }
+
+ pthread_mutex_unlock(&procevent_data_lock);
+ }