#include "common.h"
+#ifdef __FreeBSD__
+#include <sys/user.h>
+#endif
+
+// ----------------------------------------------------------------------------
+// per O/S configuration
+
+// the minimum PID of the system
+// this is also the pid of the init process
+#define INIT_PID 1
+
+// if the way apps.plugin will work, will read the entire process list,
+// including the resource utilization of each process, instantly
+// set this to 1
+// when set to 0, apps.plugin builds a sort list of processes, in order
+// to process children processes, before parent processes
+#ifdef __FreeBSD__
+#define ALL_PIDS_ARE_READ_INSTANTLY 1
+#else
+#define ALL_PIDS_ARE_READ_INSTANTLY 0
+#endif
// ----------------------------------------------------------------------------
// string lengths
debug = 0,
update_every = 1,
enable_guest_charts = 0,
+#ifdef __FreeBSD__
+ enable_file_charts = 0,
+#else
enable_file_charts = 1,
+#endif
enable_users_charts = 1,
enable_groups_charts = 1,
include_exited_childs = 1;
static size_t
global_iterations_counter = 1,
+ calls_counter = 0,
file_counter = 0;
static size_t
all_pids_count = 0; // the number of processes running
+#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
// Another pre-allocated list of all possible pids.
// We need it to pids and assign them a unique sortlist id, so that we
// read parents before children. This is needed to prevent a situation where
// its parent has accumulated its resources.
static pid_t
*all_pids_sortlist = NULL;
-
+#endif
// ----------------------------------------------------------------------------
// file descriptor
p->log_thrown |= log;
switch(log) {
case PID_LOG_IO:
- error("Cannot process %s/proc/%d/io (command '%s')", global_host_prefix, p->pid, p->comm);
+ error("Cannot process %s/proc/%d/io (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
break;
case PID_LOG_STATM:
- error("Cannot process %s/proc/%d/statm (command '%s')", global_host_prefix, p->pid, p->comm);
+ error("Cannot process %s/proc/%d/statm (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
break;
case PID_LOG_CMDLINE:
- error("Cannot process %s/proc/%d/cmdline (command '%s')", global_host_prefix, p->pid, p->comm);
+ error("Cannot process %s/proc/%d/cmdline (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
break;
case PID_LOG_FDS:
- error("Cannot process entries in %s/proc/%d/fd (command '%s')", global_host_prefix, p->pid, p->comm);
+ error("Cannot process entries in %s/proc/%d/fd (command '%s')", netdata_configured_host_prefix, p->pid, p->comm);
break;
case PID_LOG_STAT:
static inline int read_proc_pid_cmdline(struct pid_stat *p) {
+#ifdef __FreeBSD__
+ size_t i, bytes = MAX_CMDLINE;
+ int mib[4];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_ARGS;
+ mib[3] = p->pid;
+ if (unlikely(sysctl(mib, 4, p->cmdline, &bytes, NULL, 0)))
+ goto cleanup;
+#else
if(unlikely(!p->cmdline_filename)) {
char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", global_host_prefix, p->pid);
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/cmdline", netdata_configured_host_prefix, p->pid);
p->cmdline_filename = strdupz(filename);
}
close(fd);
if(unlikely(bytes < 0)) goto cleanup;
+#endif
p->cmdline[bytes] = '\0';
for(i = 0; i < bytes ; i++)
return 0;
}
-static inline int read_proc_pid_ownership(struct pid_stat *p) {
+static inline int read_proc_pid_ownership(struct pid_stat *p, void *ptr) {
+ (void)ptr;
+#ifdef __FreeBSD__
+ struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
+
+ p->uid = proc_info->ki_uid;
+ p->gid = proc_info->ki_groups[0];
+
+ return 1;
+#else
if(unlikely(!p->stat_filename)) {
error("pid %d does not have a stat_filename", p->pid);
return 0;
p->gid = st.st_gid;
return 1;
+#endif
}
-static inline int read_proc_pid_stat(struct pid_stat *p) {
+// ----------------------------------------------------------------------------
+// macro to calculate the incremental rate of a value
+// each parameter is accessed only ONCE - so it is safe to pass function calls
+// or other macros as parameters
+
+#define incremental_rate(rate_variable, last_kernel_variable, new_kernel_value, collected_usec, last_collected_usec) { \
+ kernel_uint_t _new_tmp = new_kernel_value; \
+ rate_variable = (_new_tmp - last_kernel_variable) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec); \
+ last_kernel_variable = _new_tmp; \
+ }
+
+// the same macro for struct pid members
+#define pid_incremental_rate(type, var, value) \
+ incremental_rate(var, var##_raw, value, p->type##_collected_usec, p->last_##type##_collected_usec)
+
+
+// ----------------------------------------------------------------------------
+
+static inline int read_proc_pid_stat(struct pid_stat *p, void *ptr) {
+ (void)ptr;
+
+#ifdef __FreeBSD__
+ struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
+
+ if (unlikely(proc_info->ki_tdflags & TDF_IDLETD))
+ goto cleanup;
+#else
static procfile *ff = NULL;
if(unlikely(!p->stat_filename)) {
char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/stat", global_host_prefix, p->pid);
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/stat", netdata_configured_host_prefix, p->pid);
p->stat_filename = strdupz(filename);
}
ff = procfile_readall(ff);
if(unlikely(!ff)) goto cleanup;
+#endif
p->last_stat_collected_usec = p->stat_collected_usec;
p->stat_collected_usec = now_monotonic_usec();
- file_counter++;
+ calls_counter++;
+#ifdef __FreeBSD__
+ char *comm = proc_info->ki_comm;
+ p->ppid = proc_info->ki_ppid;
+#else
// p->pid = str2pid_t(procfile_lineword(ff, 0, 0));
char *comm = procfile_lineword(ff, 0, 1);
// p->state = *(procfile_lineword(ff, 0, 2));
// p->tty_nr = (int32_t)str2pid_t(procfile_lineword(ff, 0, 6));
// p->tpgid = (int32_t)str2pid_t(procfile_lineword(ff, 0, 7));
// p->flags = str2uint64_t(procfile_lineword(ff, 0, 8));
+#endif
if(strcmp(p->comm, comm)) {
if(unlikely(debug)) {
if(p->comm[0])
fprintf(stderr, "apps.plugin: \tpid %d (%s) changed name to '%s'\n", p->pid, p->comm, comm);
else
- fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", p->pid, p->comm);
+ fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", p->pid, comm);
}
strncpyz(p->comm, comm, MAX_COMPARE_NAME);
assign_target_to_pid(p);
}
- kernel_uint_t last = p->minflt_raw;
- p->minflt_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 9));
- p->minflt = (p->minflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
-
- last = p->cminflt_raw;
- p->cminflt_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 10));
- p->cminflt = (p->cminflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
-
- last = p->majflt_raw;
- p->majflt_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 11));
- p->majflt = (p->majflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
-
- last = p->cmajflt_raw;
- p->cmajflt_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 12));
- p->cmajflt = (p->cmajflt_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+#ifdef __FreeBSD__
+ pid_incremental_rate(stat, p->minflt, (kernel_uint_t)proc_info->ki_rusage.ru_minflt);
+ pid_incremental_rate(stat, p->cminflt, (kernel_uint_t)proc_info->ki_rusage_ch.ru_minflt);
+ pid_incremental_rate(stat, p->majflt, (kernel_uint_t)proc_info->ki_rusage.ru_majflt);
+ pid_incremental_rate(stat, p->cmajflt, (kernel_uint_t)proc_info->ki_rusage_ch.ru_majflt);
+ pid_incremental_rate(stat, p->utime, (kernel_uint_t)proc_info->ki_rusage.ru_utime.tv_sec * 100 + proc_info->ki_rusage.ru_utime.tv_usec / 10000);
+ pid_incremental_rate(stat, p->stime, (kernel_uint_t)proc_info->ki_rusage.ru_stime.tv_sec * 100 + proc_info->ki_rusage.ru_stime.tv_usec / 10000);
+ pid_incremental_rate(stat, p->cutime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_utime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_utime.tv_usec / 10000);
+ pid_incremental_rate(stat, p->cstime, (kernel_uint_t)proc_info->ki_rusage_ch.ru_stime.tv_sec * 100 + proc_info->ki_rusage_ch.ru_utime.tv_usec / 10000);
- last = p->utime_raw;
- p->utime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 13));
- p->utime = (p->utime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
-
- last = p->stime_raw;
- p->stime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 14));
- p->stime = (p->stime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
-
- last = p->cutime_raw;
- p->cutime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 15));
- p->cutime = (p->cutime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
-
- last = p->cstime_raw;
- p->cstime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 16));
- p->cstime = (p->cstime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ p->num_threads = proc_info->ki_numthreads;
+ if(enable_guest_charts) {
+ enable_guest_charts = 0;
+ info("Guest charts aren't supported by FreeBSD");
+ }
+#else
+ pid_incremental_rate(stat, p->minflt, str2kernel_uint_t(procfile_lineword(ff, 0, 9)));
+ pid_incremental_rate(stat, p->cminflt, str2kernel_uint_t(procfile_lineword(ff, 0, 10)));
+ pid_incremental_rate(stat, p->majflt, str2kernel_uint_t(procfile_lineword(ff, 0, 11)));
+ pid_incremental_rate(stat, p->cmajflt, str2kernel_uint_t(procfile_lineword(ff, 0, 12)));
+ pid_incremental_rate(stat, p->utime, str2kernel_uint_t(procfile_lineword(ff, 0, 13)));
+ pid_incremental_rate(stat, p->stime, str2kernel_uint_t(procfile_lineword(ff, 0, 14)));
+ pid_incremental_rate(stat, p->cutime, str2kernel_uint_t(procfile_lineword(ff, 0, 15)));
+ pid_incremental_rate(stat, p->cstime, str2kernel_uint_t(procfile_lineword(ff, 0, 16)));
// p->priority = str2kernel_uint_t(procfile_lineword(ff, 0, 17));
// p->nice = str2kernel_uint_t(procfile_lineword(ff, 0, 18));
p->num_threads = (int32_t)str2uint32_t(procfile_lineword(ff, 0, 19));
// p->delayacct_blkio_ticks = str2kernel_uint_t(procfile_lineword(ff, 0, 41));
if(enable_guest_charts) {
- last = p->gtime_raw;
- p->gtime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 42));
- p->gtime = (p->gtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- last = p->cgtime_raw;
- p->cgtime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 43));
- p->cgtime = (p->cgtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ pid_incremental_rate(stat, p->gtime, str2kernel_uint_t(procfile_lineword(ff, 0, 42)));
+ pid_incremental_rate(stat, p->cgtime, str2kernel_uint_t(procfile_lineword(ff, 0, 43)));
if (show_guest_time || p->gtime || p->cgtime) {
p->utime -= (p->utime >= p->gtime) ? p->gtime : p->utime;
show_guest_time = 1;
}
}
+#endif
if(unlikely(debug || (p->target && p->target->debug)))
- fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT ", threads=%d\n", global_host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
+ fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' on target '%s' (dt=%llu) VALUES: utime=" KERNEL_UINT_FORMAT ", stime=" KERNEL_UINT_FORMAT ", cutime=" KERNEL_UINT_FORMAT ", cstime=" KERNEL_UINT_FORMAT ", minflt=" KERNEL_UINT_FORMAT ", majflt=" KERNEL_UINT_FORMAT ", cminflt=" KERNEL_UINT_FORMAT ", cmajflt=" KERNEL_UINT_FORMAT ", threads=%d\n", netdata_configured_host_prefix, p->pid, p->comm, (p->target)?p->target->name:"UNSET", p->stat_collected_usec - p->last_stat_collected_usec, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
if(unlikely(global_iterations_counter == 1)) {
p->minflt = 0;
return 0;
}
-static inline int read_proc_pid_statm(struct pid_stat *p) {
+static inline int read_proc_pid_statm(struct pid_stat *p, void *ptr) {
+ (void)ptr;
+#ifdef __FreeBSD__
+ struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
+#else
static procfile *ff = NULL;
if(unlikely(!p->statm_filename)) {
char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/statm", global_host_prefix, p->pid);
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/statm", netdata_configured_host_prefix, p->pid);
p->statm_filename = strdupz(filename);
}
ff = procfile_readall(ff);
if(unlikely(!ff)) goto cleanup;
+#endif
- file_counter++;
+ calls_counter++;
+#ifdef __FreeBSD__
+ p->statm_size = proc_info->ki_size / sysconf(_SC_PAGESIZE);
+ p->statm_resident = proc_info->ki_rssize;
+ p->statm_share = 0; // do we have to use ru_ixrss here?
+#else
p->statm_size = str2kernel_uint_t(procfile_lineword(ff, 0, 0));
p->statm_resident = str2kernel_uint_t(procfile_lineword(ff, 0, 1));
p->statm_share = str2kernel_uint_t(procfile_lineword(ff, 0, 2));
// p->statm_lib = str2kernel_uint_t(procfile_lineword(ff, 0, 4));
// p->statm_data = str2kernel_uint_t(procfile_lineword(ff, 0, 5));
// p->statm_dirty = str2kernel_uint_t(procfile_lineword(ff, 0, 6));
+#endif
return 1;
return 0;
}
-static inline int read_proc_pid_io(struct pid_stat *p) {
+static inline int read_proc_pid_io(struct pid_stat *p, void *ptr) {
+ (void)ptr;
+#ifdef __FreeBSD__
+ struct kinfo_proc *proc_info = (struct kinfo_proc *)ptr;
+#else
static procfile *ff = NULL;
if(unlikely(!p->io_filename)) {
char filename[FILENAME_MAX + 1];
- snprintfz(filename, FILENAME_MAX, "%s/proc/%d/io", global_host_prefix, p->pid);
+ snprintfz(filename, FILENAME_MAX, "%s/proc/%d/io", netdata_configured_host_prefix, p->pid);
p->io_filename = strdupz(filename);
}
ff = procfile_readall(ff);
if(unlikely(!ff)) goto cleanup;
+#endif
- file_counter++;
+ calls_counter++;
p->last_io_collected_usec = p->io_collected_usec;
p->io_collected_usec = now_monotonic_usec();
- kernel_uint_t last;
-
- last = p->io_logical_bytes_read_raw;
- p->io_logical_bytes_read_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 1));
- p->io_logical_bytes_read = (p->io_logical_bytes_read_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
-
- last = p->io_logical_bytes_written_raw;
- p->io_logical_bytes_written_raw = str2kernel_uint_t(procfile_lineword(ff, 1, 1));
- p->io_logical_bytes_written = (p->io_logical_bytes_written_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
-
- // last = p->io_read_calls_raw;
- // p->io_read_calls_raw = str2kernel_uint_t(procfile_lineword(ff, 2, 1));
- // p->io_read_calls = (p->io_read_calls_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
-
- // last = p->io_write_calls_raw;
- // p->io_write_calls_raw = str2kernel_uint_t(procfile_lineword(ff, 3, 1));
- // p->io_write_calls = (p->io_write_calls_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
-
- last = p->io_storage_bytes_read_raw;
- p->io_storage_bytes_read_raw = str2kernel_uint_t(procfile_lineword(ff, 4, 1));
- p->io_storage_bytes_read = (p->io_storage_bytes_read_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
-
- last = p->io_storage_bytes_written_raw;
- p->io_storage_bytes_written_raw = str2kernel_uint_t(procfile_lineword(ff, 5, 1));
- p->io_storage_bytes_written = (p->io_storage_bytes_written_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
-
- // last = p->io_cancelled_write_bytes_raw;
- // p->io_cancelled_write_bytes_raw = str2kernel_uint_t(procfile_lineword(ff, 6, 1));
- // p->io_cancelled_write_bytes = (p->io_cancelled_write_bytes_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (p->io_collected_usec - p->last_io_collected_usec);
+#ifdef __FreeBSD__
+ pid_incremental_rate(io, p->io_storage_bytes_read, proc_info->ki_rusage.ru_inblock);
+ pid_incremental_rate(io, p->io_storage_bytes_written, proc_info->ki_rusage.ru_oublock);
+#else
+ pid_incremental_rate(io, p->io_logical_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 0, 1)));
+ pid_incremental_rate(io, p->io_logical_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 1, 1)));
+ // pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1)));
+ // pid_incremental_rate(io, p->io_write_calls, str2kernel_uint_t(procfile_lineword(ff, 3, 1)));
+ pid_incremental_rate(io, p->io_storage_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 4, 1)));
+ pid_incremental_rate(io, p->io_storage_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 5, 1)));
+ // pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1)));
+#endif
if(unlikely(global_iterations_counter == 1)) {
p->io_logical_bytes_read = 0;
}
static inline int read_proc_stat() {
+#ifdef __FreeBSD__
+ long cp_time[CPUSTATES];
+ int i;
+
+ if (unlikely(CPUSTATES != 5)) {
+ error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
+ goto cleanup;
+ }
+ if (unlikely(GETSYSCTL_BY_NAME("kern.cp_time", cp_time))) goto cleanup;
+#else
static char filename[FILENAME_MAX + 1] = "";
static procfile *ff = NULL;
+#endif
static kernel_uint_t utime_raw = 0, stime_raw = 0, gtime_raw = 0, gntime_raw = 0, ntime_raw = 0;
static usec_t collected_usec = 0, last_collected_usec = 0;
+#ifndef __FreeBSD__
if(unlikely(!ff)) {
- snprintfz(filename, FILENAME_MAX, "%s/proc/stat", global_host_prefix);
+ snprintfz(filename, FILENAME_MAX, "%s/proc/stat", netdata_configured_host_prefix);
ff = procfile_open(filename, " \t:", PROCFILE_FLAG_DEFAULT);
if(unlikely(!ff)) goto cleanup;
}
ff = procfile_readall(ff);
if(unlikely(!ff)) goto cleanup;
+#endif
last_collected_usec = collected_usec;
collected_usec = now_monotonic_usec();
- file_counter++;
+ calls_counter++;
- kernel_uint_t last;
+ // temporary - it is added global_ntime;
+ kernel_uint_t global_ntime = 0;
- last = utime_raw;
- utime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 1));
- global_utime = (utime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
-
- // nice time, on user time
- last = ntime_raw;
- ntime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 2));
- global_utime += (ntime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
-
- last = stime_raw;
- stime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 3));
- global_stime = (stime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
+#ifdef __FreeBSD__
+ incremental_rate(global_utime, utime_raw, cp_time[0], collected_usec, last_collected_usec);
+ incremental_rate(global_ntime, ntime_raw, cp_time[1], collected_usec, last_collected_usec);
+ incremental_rate(global_stime, stime_raw, cp_time[2], collected_usec, last_collected_usec);
+#else
+ incremental_rate(global_utime, utime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 1)), collected_usec, last_collected_usec);
+ incremental_rate(global_ntime, ntime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 2)), collected_usec, last_collected_usec);
+ incremental_rate(global_stime, stime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 3)), collected_usec, last_collected_usec);
+ incremental_rate(global_gtime, gtime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 10)), collected_usec, last_collected_usec);
+#endif
- last = gtime_raw;
- gtime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 10));
- global_gtime = (gtime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
+ global_utime += global_ntime;
+#ifdef __FreeBSD__
+ if(enable_guest_charts) {
+ enable_guest_charts = 0;
+ info("Guest charts aren't supported by FreeBSD");
+ }
+#else
if(enable_guest_charts) {
+ // temporary - it is added global_ntime;
+ kernel_uint_t global_gntime = 0;
+
// guest nice time, on guest time
- last = gntime_raw;
- gntime_raw = str2kernel_uint_t(procfile_lineword(ff, 0, 11));
- global_gtime += (gntime_raw - last) * (USEC_PER_SEC * RATES_DETAIL) / (collected_usec - last_collected_usec);
+ incremental_rate(global_gntime, gntime_raw, str2kernel_uint_t(procfile_lineword(ff, 0, 11)), collected_usec, last_collected_usec);
+
+ global_gtime += global_gntime;
// remove guest time from user time
global_utime -= (global_utime > global_gtime) ? global_gtime : global_utime;
}
+#endif
if(unlikely(global_iterations_counter == 1)) {
global_utime = 0;
}
static inline void cleanup_negative_pid_fds(struct pid_stat *p) {
- int *fd = p->fds, *end = &p->fds[p->fds_size];
- while(fd < end) {
+ int *fd = p->fds, *fdend = &p->fds[p->fds_size];
+
+ while(fd < fdend) {
if(unlikely(*fd < 0)) {
file_descriptor_not_used(-(*fd));
*fd++ = 0;
while(fd < end) *fd++ = 0;
}
-static inline int read_pid_file_descriptors(struct pid_stat *p) {
+static inline int read_pid_file_descriptors(struct pid_stat *p, void *ptr) {
+ (void)ptr;
+#ifdef __FreeBSD__
+ int mib[4];
+ size_t size;
+ struct kinfo_file *fds;
+ static char *fdsbuf;
+ char *bfdsbuf, *efdsbuf;
+ char fdsname[FILENAME_MAX + 1];
+
+ // we make all pid fds negative, so that
+ // we can detect unused file descriptors
+ // at the end, to free them
+ make_all_pid_fds_negative(p);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_FILEDESC;
+ mib[3] = p->pid;
+
+ if (unlikely(sysctl(mib, 4, NULL, &size, NULL, 0))) {
+ error("sysctl error: Can't get file descriptors data size for pid %d", p->pid);
+ return 0;
+ }
+ if (likely(size > 0))
+ fdsbuf = reallocz(fdsbuf, size);
+ if (unlikely(sysctl(mib, 4, fdsbuf, &size, NULL, 0))) {
+ error("sysctl error: Can't get file descriptors data for pid %d", p->pid);
+ return 0;
+ }
+
+ bfdsbuf = fdsbuf;
+ efdsbuf = fdsbuf + size;
+ while (bfdsbuf < efdsbuf) {
+ fds = (struct kinfo_file *)(uintptr_t)bfdsbuf;
+ if (unlikely(fds->kf_structsize == 0))
+ break;
+
+ // do not process file descriptors for current working directory, root directory,
+ // jail directory, ktrace vnode, text vnode and controlling terminal
+ if (unlikely(fds->kf_fd < 0)) {
+ bfdsbuf += fds->kf_structsize;
+ continue;
+ }
+
+ // get file descriptors array index
+ int fdid = fds->kf_fd;
+
+ // check if the fds array is small
+ if (unlikely(fdid >= p->fds_size)) {
+ // it is small, extend it
+
+ if (unlikely(debug))
+ fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + MAX_SPARE_FDS);
+
+ p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int));
+
+ // and initialize it
+ zero_pid_fds(p, p->fds_size, (fdid + MAX_SPARE_FDS) - p->fds_size);
+ p->fds_size = fdid + MAX_SPARE_FDS;
+ }
+
+ if (unlikely(p->fds[fdid] == 0)) {
+ // we don't know this fd, get it
+
+ switch (fds->kf_type) {
+ case KF_TYPE_FIFO:
+ case KF_TYPE_VNODE:
+ if (unlikely(!fds->kf_path[0])) {
+ sprintf(fdsname, "other: inode: %lu", fds->kf_un.kf_file.kf_file_fileid);
+ break;
+ }
+ sprintf(fdsname, "%s", fds->kf_path);
+ break;
+ case KF_TYPE_SOCKET:
+ switch (fds->kf_sock_domain) {
+ case AF_INET:
+ case AF_INET6:
+ if (fds->kf_sock_protocol == IPPROTO_TCP)
+ sprintf(fdsname, "socket: %d %lx", fds->kf_sock_protocol, fds->kf_un.kf_sock.kf_sock_inpcb);
+ else
+ sprintf(fdsname, "socket: %d %lx", fds->kf_sock_protocol, fds->kf_un.kf_sock.kf_sock_pcb);
+ break;
+ case AF_UNIX:
+ /* print address of pcb and connected pcb */
+ sprintf(fdsname, "socket: %lx %lx", fds->kf_un.kf_sock.kf_sock_pcb, fds->kf_un.kf_sock.kf_sock_unpconn);
+ break;
+ default:
+ /* print protocol number and socket address */
+ sprintf(fdsname, "socket: other: %d %s %s", fds->kf_sock_protocol, fds->kf_sa_local.__ss_pad1, fds->kf_sa_local.__ss_pad2);
+ }
+ break;
+ case KF_TYPE_PIPE:
+ sprintf(fdsname, "pipe: %lu %lu", fds->kf_un.kf_pipe.kf_pipe_addr, fds->kf_un.kf_pipe.kf_pipe_peer);
+ break;
+ case KF_TYPE_PTS:
+ sprintf(fdsname, "other: pts: %u", fds->kf_un.kf_pts.kf_pts_dev);
+ break;
+ case KF_TYPE_SHM:
+ sprintf(fdsname, "other: shm: %s size: %lu", fds->kf_path, fds->kf_un.kf_file.kf_file_size);
+ break;
+ case KF_TYPE_SEM:
+ sprintf(fdsname, "other: sem: %u", fds->kf_un.kf_sem.kf_sem_value);
+ break;
+ default:
+ sprintf(fdsname, "other: pid: %d fd: %d", fds->kf_un.kf_proc.kf_pid, fds->kf_fd);
+ }
+
+ // if another process already has this, we will get
+ // the same id
+ p->fds[fdid] = file_descriptor_find_or_add(fdsname);
+ }
+
+ // else make it positive again, we need it
+ // of course, the actual file may have changed, but we don't care so much
+ // FIXME: we could compare the inode as returned by readdir dirent structure
+
+ else
+ p->fds[fdid] = -p->fds[fdid];
+
+ bfdsbuf += fds->kf_structsize;
+ }
+#else
if(unlikely(!p->fds_dirname)) {
char dirname[FILENAME_MAX+1];
- snprintfz(dirname, FILENAME_MAX, "%s/proc/%d/fd", global_host_prefix, p->pid);
+ snprintfz(dirname, FILENAME_MAX, "%s/proc/%d/fd", netdata_configured_host_prefix, p->pid);
p->fds_dirname = strdupz(dirname);
}
continue;
// get its number
- int fdid = (int)str2l(de->d_name);
+ int fdid = (int) str2l(de->d_name);
if(unlikely(fdid < 0)) continue;
// check if the fds array is small
// it is small, extend it
if(unlikely(debug))
- fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + MAX_SPARE_FDS);
+ fprintf(stderr
+ , "apps.plugin: extending fd memory slots for %s from %d to %d\n"
+ , p->comm
+ , p->fds_size
+ , fdid + MAX_SPARE_FDS
+ );
p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int));
if(unlikely(p->fds[fdid] == 0)) {
// we don't know this fd, get it
- sprintf(fdname, "%s/proc/%d/fd/%s", global_host_prefix, p->pid, de->d_name);
+ sprintf(fdname, "%s/proc/%d/fd/%s", netdata_configured_host_prefix, p->pid, de->d_name);
ssize_t l = readlink(fdname, linkname, FILENAME_MAX);
if(unlikely(l == -1)) {
if(debug || (p->target && p->target->debug)) {
p->fds[fdid] = file_descriptor_find_or_add(linkname);
}
- // else make it positive again, we need it
- // of course, the actual file may have changed, but we don't care so much
- // FIXME: we could compare the inode as returned by readdir dirent structure
+ // else make it positive again, we need it
+ // of course, the actual file may have changed, but we don't care so much
+ // FIXME: we could compare the inode as returned by readdir dirent structure
+ // UPDATE: no we cannot use inodes - under /proc inodes don't change when the link is changed
else
p->fds[fdid] = -p->fds[fdid];
}
closedir(fds);
+#endif
cleanup_negative_pid_fds(p);
return 1;
if(p->updated || !p->stat_collected_usec)
continue;
- kernel_uint_t utime = (p->utime_raw + p->cutime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- kernel_uint_t stime = (p->stime_raw + p->cstime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- kernel_uint_t gtime = (p->gtime_raw + p->cgtime_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- kernel_uint_t minflt = (p->minflt_raw + p->cminflt_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
- kernel_uint_t majflt = (p->majflt_raw + p->cmajflt_raw) * (1000000ULL * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ kernel_uint_t utime = (p->utime_raw + p->cutime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ kernel_uint_t stime = (p->stime_raw + p->cstime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ kernel_uint_t gtime = (p->gtime_raw + p->cgtime_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ kernel_uint_t minflt = (p->minflt_raw + p->cminflt_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
+ kernel_uint_t majflt = (p->majflt_raw + p->cmajflt_raw) * (USEC_PER_SEC * RATES_DETAIL) / (p->stat_collected_usec - p->last_stat_collected_usec);
if(utime + stime + gtime + minflt + majflt == 0)
continue;
return 1;
}
-static inline int collect_data_for_pid(pid_t pid) {
- if(unlikely(pid <= 0 || pid > pid_max)) {
- error("Invalid pid %d read (expected 1 to %d). Ignoring process.", pid, pid_max);
+static inline int collect_data_for_pid(pid_t pid, void *ptr) {
+ if(unlikely(pid < INIT_PID || pid > pid_max)) {
+ error("Invalid pid %d read (expected %d to %d). Ignoring process.", pid, INIT_PID, pid_max);
return 0;
}
// --------------------------------------------------------------------
// /proc/<pid>/stat
- if(unlikely(!managed_log(p, PID_LOG_STAT, read_proc_pid_stat(p))))
+ if(unlikely(!managed_log(p, PID_LOG_STAT, read_proc_pid_stat(p, ptr))))
// there is no reason to proceed if we cannot get its status
return 0;
- read_proc_pid_ownership(p);
+ read_proc_pid_ownership(p, ptr);
// check its parent pid
if(unlikely(p->ppid < 0 || p->ppid > pid_max)) {
// --------------------------------------------------------------------
// /proc/<pid>/io
- managed_log(p, PID_LOG_IO, read_proc_pid_io(p));
+ managed_log(p, PID_LOG_IO, read_proc_pid_io(p, ptr));
// --------------------------------------------------------------------
// /proc/<pid>/statm
- if(unlikely(!managed_log(p, PID_LOG_STATM, read_proc_pid_statm(p))))
+ if(unlikely(!managed_log(p, PID_LOG_STATM, read_proc_pid_statm(p, ptr))))
// there is no reason to proceed if we cannot get its memory status
return 0;
// /proc/<pid>/fd
if(enable_file_charts)
- managed_log(p, PID_LOG_FDS, read_pid_file_descriptors(p));
+ managed_log(p, PID_LOG_FDS, read_pid_file_descriptors(p, ptr));
// --------------------------------------------------------------------
// done!
static int collect_data_for_all_processes(void) {
struct pid_stat *p = NULL;
+#ifdef __FreeBSD__
+ int i, procnum;
+ size_t procbase_size;
+ static struct kinfo_proc *procbase;
+
+ int mib[3];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PROC;
+ if (unlikely(sysctl(mib, 3, NULL, &procbase_size, NULL, 0))) {
+ error("sysctl error: Can't get processes data size");
+ return 0;
+ }
+ procbase = reallocz(procbase, procbase_size);
+ if (unlikely(sysctl(mib, 3, procbase, &procbase_size, NULL, 0))) {
+ error("sysctl error: Can't get processes data");
+ return 0;
+ }
+ procnum = procbase_size / sizeof(struct kinfo_proc);
+#endif
+
if(all_pids_count) {
size_t slc = 0;
for(p = root_of_pids; p ; p = p->next) {
p->children_count = 0;
p->parent = NULL;
+#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
all_pids_sortlist[slc++] = p->pid;
+#endif
}
+#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
if(unlikely(slc != all_pids_count)) {
error("Internal error: I was thinking I had %zu processes in my arrays, but it seems there are more.", all_pids_count);
all_pids_count = slc;
// we forward read all running processes
// collect_data_for_pid() is smart enough,
- // not to read the same pid twice per iterations
+ // not to read the same pid twice per iteration
for(slc = 0; slc < all_pids_count; slc++)
- collect_data_for_pid(all_pids_sortlist[slc]);
+ collect_data_for_pid(all_pids_sortlist[slc], NULL);
}
+#endif
}
+#ifdef __FreeBSD__
+ for (i = INIT_PID; i < procnum - INIT_PID; ++i) {
+ pid_t pid = procbase[i].ki_pid;
+ collect_data_for_pid(pid, &procbase[i]);
+ }
+#else
char dirname[FILENAME_MAX + 1];
- snprintfz(dirname, FILENAME_MAX, "%s/proc", global_host_prefix);
+ snprintfz(dirname, FILENAME_MAX, "%s/proc", netdata_configured_host_prefix);
DIR *dir = opendir(dirname);
if(!dir) return 0;
if(unlikely(endptr == de->d_name || *endptr != '\0'))
continue;
- collect_data_for_pid(pid);
+ collect_data_for_pid(pid, NULL);
}
closedir(dir);
+#endif
if(!all_pids_count)
return 0;
if(unlikely(debug && (p->keep || p->keeploops)))
fprintf(stderr, " > CLEANUP cannot keep exited process %d (%s) anymore - removing it.\n", p->pid, p->comm);
- for(c = 0 ; c < p->fds_size ; c++) if(p->fds[c] > 0) {
- file_descriptor_not_used(p->fds[c]);
- p->fds[c] = 0;
- }
+ for(c = 0; c < p->fds_size; c++)
+ if(p->fds[c] > 0) {
+ file_descriptor_not_used(p->fds[c]);
+ p->fds[c] = 0;
+ }
pid_t r = p->pid;
p = p->next;
&& p->parent
&& p->parent->children_count
&& (p->target == p->parent->target || !p->parent->target)
- && p->ppid != 1
+ && p->ppid != INIT_PID
)) {
p->parent->children_count--;
p->merged = 1;
}
// init goes always to default target
- if(all_pids[1])
- all_pids[1]->target = apps_groups_default_target;
+ if(all_pids[INIT_PID])
+ all_pids[INIT_PID]->target = apps_groups_default_target;
// give a default target on all top level processes
if(unlikely(debug)) loops++;
"DIMENSION user '' incremental 1 1000\n"
"DIMENSION system '' incremental 1 1000\n"
"CHART netdata.apps_files '' 'Apps Plugin Files' 'files/s' apps.plugin netdata.apps_files line 140001 %1$d\n"
+ "DIMENSION calls '' incremental 1 1\n"
"DIMENSION files '' incremental 1 1\n"
"DIMENSION pids '' absolute 1 1\n"
"DIMENSION fds '' absolute 1 1\n"
"SET system = %llu\n"
"END\n"
"BEGIN netdata.apps_files %llu\n"
+ "SET calls = %zu\n"
"SET files = %zu\n"
"SET pids = %zu\n"
"SET fds = %d\n"
, cpuuser
, cpusyst
, usec
+ , calls_counter
, file_counter
, all_pids_count
, all_files_len
}
send_END();
+#ifndef __FreeBSD__
send_BEGIN(type, "lreads", usec);
for (w = root; w ; w = w->next) {
if(unlikely(w->exposed))
send_SET(w->name, w->io_logical_bytes_written);
}
send_END();
+#endif
send_BEGIN(type, "preads", usec);
for (w = root; w ; w = w->next) {
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
}
+#ifndef __FreeBSD__
fprintf(stdout, "CHART %s.lreads '' '%s Disk Logical Reads' 'kilobytes/s' disk %s.lreads stacked 20042 %d\n", type, title, type, update_every);
for (w = root; w ; w = w->next) {
if(unlikely(w->exposed))
if(unlikely(w->exposed))
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
}
+#endif
+
+#ifdef __FreeBSD__
+ fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'blocks/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
+ for (w = root; w ; w = w->next) {
+ if(unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
+ }
+ fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'blocks/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
+ for (w = root; w ; w = w->next) {
+ if(unlikely(w->exposed))
+ fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
+ }
+#else
fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'kilobytes/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
for (w = root; w ; w = w->next) {
if(unlikely(w->exposed))
if(unlikely(w->exposed))
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
}
+#endif
if(enable_file_charts) {
fprintf(stdout, "CHART %s.files '' '%s Open Files' 'open files' disk %s.files stacked 20050 %d\n", type,
// ----------------------------------------------------------------------------
// parse command line arguments
+int check_proc_1_io() {
+ int ret = 0;
+
+ procfile *ff = procfile_open("/proc/1/io", NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
+ if(!ff) goto cleanup;
+
+ ff = procfile_readall(ff);
+ if(!ff) goto cleanup;
+
+ ret = 1;
+
+cleanup:
+ procfile_close(ff);
+ return ret;
+}
+
static void parse_args(int argc, char **argv)
{
int i, freq = 0;
exit(0);
}
+ if(strcmp("test-permissions", argv[i]) == 0 || strcmp("-t", argv[i]) == 0) {
+ if(!check_proc_1_io()) {
+ perror("Tried to read /proc/1/io and it failed");
+ exit(1);
+ }
+ printf("OK\n");
+ exit(0);
+ }
+
if(strcmp("debug", argv[i]) == 0) {
debug = 1;
// debug_flags = 0xffffffff;
"\n"
" netdata apps.plugin %s\n"
" Copyright (C) 2016-2017 Costa Tsaousis <costa@tsaousis.gr>\n"
- " Released under GNU Public License v3 or later.\n"
+ " Released under GNU General Public License v3 or later.\n"
" All rights reserved.\n"
"\n"
" This program is a data collector plugin for netdata.\n"
// set the name for logging
program_name = "apps.plugin";
- info("started on pid %d", getpid());
-
// disable syslog for apps.plugin
error_log_syslog = 0;
error_log_errors_per_period = 100;
error_log_throttle_period = 3600;
- global_host_prefix = getenv("NETDATA_HOST_PREFIX");
- if(global_host_prefix == NULL) {
+ netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX");
+ if(netdata_configured_host_prefix == NULL) {
// info("NETDATA_HOST_PREFIX is not passed from netdata");
- global_host_prefix = "";
+ netdata_configured_host_prefix = "";
}
- // else info("Found NETDATA_HOST_PREFIX='%s'", global_host_prefix);
+ // else info("Found NETDATA_HOST_PREFIX='%s'", netdata_configured_host_prefix);
config_dir = getenv("NETDATA_CONFIG_DIR");
if(config_dir == NULL) {
struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
if(setrlimit(RLIMIT_CORE, &rl) != 0)
info("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
+#ifdef HAVE_SYS_PRCTL_H
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
+#endif
}
#endif /* NETDATA_INTERNAL_CHECKS */
parse_args(argc, argv);
- if(!check_capabilities()) {
- if(!am_i_running_as_root()) {
- uid_t uid = getuid(), euid = geteuid();
+ if(!check_capabilities() && !am_i_running_as_root() && !check_proc_1_io()) {
+ uid_t uid = getuid(), euid = geteuid();
#ifdef HAVE_CAPABILITY
- error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
- "Without these, apps.plugin cannot report disk I/O utilization of other processes. "
- "To enable capabilities run: sudo setcap cap_dac_read_search,cap_sys_ptrace+ep %s; "
- "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; "
- , uid, euid, argv[0], argv[0], argv[0]
- );
+ error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
+ "Without these, apps.plugin cannot report disk I/O utilization of other processes. "
+ "To enable capabilities run: sudo setcap cap_dac_read_search,cap_sys_ptrace+ep %s; "
+ "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; "
+ , uid, euid, argv[0], argv[0], argv[0]
+ );
#else
- error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
- "Without these, apps.plugin cannot report disk I/O utilization of other processes. "
- "Your system does not support capabilities. "
- "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; "
- , uid, euid, argv[0], argv[0]
- );
+ error("apps.plugin should either run as root (now running with uid %u, euid %u) or have special capabilities. "
+ "Without these, apps.plugin cannot report disk I/O utilization of other processes. "
+ "Your system does not support capabilities. "
+ "To enable setuid to root run: sudo chown root %s; sudo chmod 4755 %s; "
+ , uid, euid, argv[0], argv[0]
+ );
#endif
- }
}
+ info("started on pid %d", getpid());
+
+#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max);
+#endif
+
all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max);
usec_t step = update_every * USEC_PER_SEC;