X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fprocevent.c;h=924049f5f16c793dfd5066815aa0badc019288b1;hb=f165a8908666d40e23eaff3faf0ae3195044f1b6;hp=aba6617818b4a7633a83521fdcfdb93e962e53dc;hpb=9ea8cdcd472d3fbf177bf7ea3efac466495bedab;p=collectd.git diff --git a/src/procevent.c b/src/procevent.c index aba66178..924049f5 100644 --- a/src/procevent.c +++ b/src/procevent.c @@ -112,7 +112,8 @@ typedef struct { struct processlist_s { char *process; - uint32_t pid; + long pid; + int32_t last_status; struct processlist_s *next; }; @@ -510,11 +511,17 @@ static processlist_t *process_check(int pid) { if (pl->pid == pid) { // this is a match, and we've already stored the exact pid/name combo + DEBUG("procevent plugin: found exact match with name %s, PID %ld for " + "incoming PID %d", + pl->process, pl->pid, pid); match = pl; break; } else if (pl->pid == -1) { // this is a match, and we've found a candidate processlist_t to store // this new pid/name combo + DEBUG("procevent plugin: reusing pl object with PID %ld for incoming " + "PID %d", + pl->pid, pid); pl->pid = pid; match = pl; break; @@ -522,6 +529,9 @@ static processlist_t *process_check(int pid) { // this is a match, but another instance of this process has already // claimed this pid/name combo, // so keep looking + DEBUG("procevent plugin: found pl object with matching name for " + "incoming PID %d, but object is in use by PID %ld", + pid, pl->pid); match = pl; continue; } @@ -703,7 +713,7 @@ static int nl_connect() { nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (nl_sock == -1) { - ERROR("procevent plugin: socket open failed."); + ERROR("procevent plugin: socket open failed: %d", errno); return -1; } @@ -713,7 +723,7 @@ static int nl_connect() { rc = bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl)); if (rc == -1) { - ERROR("procevent plugin: socket bind failed."); + ERROR("procevent plugin: socket bind failed: %d", errno); close(nl_sock); return -1; } @@ -744,7 +754,8 @@ static int set_proc_ev_listen(bool enable) { rc = send(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); if (rc == -1) { - ERROR("procevent plugin: subscribing to netlink process events failed."); + ERROR("procevent plugin: subscribing to netlink process events failed: %d", + errno); return -1; } @@ -768,72 +779,82 @@ static int read_event() { if (nl_sock == -1) return ret; - status = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); + while (42) { - if (status == 0) { - return 0; - } else if (status == -1) { - if (errno != EINTR) { - ERROR("procevent plugin: socket receive error: %d", errno); - return -1; + pthread_mutex_lock(&procevent_lock); + + if (procevent_thread_loop <= 0) + return ret; + + pthread_mutex_unlock(&procevent_lock); + + status = recv(nl_sock, &nlcn_msg, sizeof(nlcn_msg), 0); + + if (status == 0) { + return 0; + } else if (status == -1) { + if (errno != EINTR) { + ERROR("procevent plugin: socket receive error: %d", errno); + return -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; - } + 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 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_lock); + if (proc_status != -1) { + pthread_mutex_lock(&procevent_lock); - int next = ring.head + 1; - if (next >= ring.maxLen) - next = 0; + int next = ring.head + 1; + if (next >= ring.maxLen) + next = 0; - if (next == ring.tail) { - WARNING("procevent plugin: ring buffer full"); - } 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()); + if (next == ring.tail) { + WARNING("procevent plugin: ring buffer full"); } 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()); + 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; } - ring.head = next; + pthread_mutex_unlock(&procevent_lock); } - - pthread_mutex_unlock(&procevent_lock); } return ret; @@ -1104,19 +1125,27 @@ static int procevent_read(void) /* {{{ */ "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 (pl != NULL) { + // 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]); - DEBUG( - "procevent plugin: PID %d (%s) STARTED, adding PID to process list", - pl->pid, pl->process); + + pl->last_status = PROCEVENT_STARTED; + + DEBUG("procevent plugin: PID %ld (%s) STARTED, adding PID to process " + "list", + pl->pid, pl->process); } }