Processes: in ps_read_status fix check to skip lines
[collectd.git] / src / processes.c
index 68f30a5..1c5b963 100644 (file)
 /* #endif HAVE_PROCINFO_H */
 
 #elif KERNEL_SOLARIS
+/* Hack: Avoid #error when building a 32-bit binary with
+ * _FILE_OFFSET_BITS=64. There is a reason for this #error, as one
+ * of the structures in <sys/procfs.h> uses an off_t, but that
+ * isn't relevant to our usage of procfs. */
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#  define SAVE_FOB_64
+#  undef _FILE_OFFSET_BITS
+#endif
+
 # include <procfs.h>
+
+#ifdef SAVE_FOB_64
+#  define _FILE_OFFSET_BITS 64
+#  undef SAVE_FOB_64
+#endif
+
 # include <dirent.h>
 /* #endif KERNEL_SOLARIS */
 
@@ -790,8 +805,8 @@ static int ps_read_tasks (int pid)
        return ((count >= 1) ? count : 1);
 } /* int *ps_read_tasks */
 
-/* Read advanced virtual memory data from /proc/pid/status */
-static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
+/* Read data from /proc/pid/status */
+static procstat_t *ps_read_status (int pid, procstat_t *ps)
 {
        FILE *fh;
        char buffer[1024];
@@ -799,6 +814,7 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
        unsigned long long lib = 0;
        unsigned long long exe = 0;
        unsigned long long data = 0;
+       unsigned long long threads = 0;
        char *fields[8];
        int numfields;
 
@@ -811,7 +827,8 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
                long long tmp;
                char *endptr;
 
-               if (strncmp (buffer, "Vm", 2) != 0)
+               if (strncmp (buffer, "Vm", 2) != 0
+                               && strncmp (buffer, "Threads", 7) != 0)
                        continue;
 
                numfields = strsplit (buffer, fields,
@@ -837,6 +854,10 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
                        {
                                exe = tmp;
                        }
+                       else if  (strncmp(buffer, "Threads", 7) == 0)
+                       {
+                               threads = tmp;
+                       }
                }
        } /* while (fgets) */
 
@@ -849,6 +870,7 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
 
        ps->vmem_data = data * 1024;
        ps->vmem_code = (exe + lib) * 1024;
+       ps->num_lwp = threads;
 
        return (ps);
 } /* procstat_t *ps_read_vmem */
@@ -991,10 +1013,21 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
        }
        else
        {
-               if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 )
+               if ( (ps_read_status(pid, ps)) == NULL)
+               {
+                       /* No VMem data */
+                       ps->vmem_data = -1;
+                       ps->vmem_code = -1;
+                       ps->num_lwp  = 0;
+                       DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
+               }
+               if ( ps->num_lwp <= 0)
                {
-                       /* returns -1 => kernel 2.4 */
-                       ps->num_lwp = 1;
+                       if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 )
+                       {
+                               /* returns -1 => kernel 2.4 */
+                               ps->num_lwp = 1;
+                       }
                }
                ps->num_proc = 1;
        }
@@ -1028,14 +1061,6 @@ int ps_read_process (int pid, procstat_t *ps, char *state)
        cpu_system_counter = cpu_system_counter * 1000000 / CONFIG_HZ;
        vmem_rss = vmem_rss * pagesize_g;
 
-       if ( (ps_read_vmem(pid, ps)) == NULL)
-       {
-               /* No VMem data */
-               ps->vmem_data = -1;
-               ps->vmem_code = -1;
-               DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
-       }
-
        ps->cpu_user_counter = cpu_user_counter;
        ps->cpu_system_counter = cpu_system_counter;
        ps->vmem_size = (unsigned long) vmem_size;
@@ -1199,17 +1224,17 @@ static int read_fork_rate ()
 #endif /*KERNEL_LINUX */
 
 #if KERNEL_SOLARIS
-static const char *ps_get_cmdline (pid_t pid, /* {{{ */
+static const char *ps_get_cmdline (long pid, /* {{{ */
                char *buffer, size_t buffer_size)
 {
        char path[PATH_MAX];
        psinfo_t info;
        int status;
 
-       snprintf(path, sizeof (path), "/proc/%i/psinfo", pid);
+       snprintf(path, sizeof (path), "/proc/%li/psinfo", pid);
 
        status = read_file_contents (path, (void *) &info, sizeof (info));
-       if (status != ((int) buffer_size))
+       if (status != sizeof (info))
        {
                ERROR ("processes plugin: Unexpected return value "
                                "while reading \"%s\": "
@@ -1230,7 +1255,7 @@ static const char *ps_get_cmdline (pid_t pid, /* {{{ */
  * The values for input and ouput chars are calculated "by hand"
  * Added a few "solaris" specific process states as well
  */
-static int ps_read_process(int pid, procstat_t *ps, char *state)
+static int ps_read_process(long pid, procstat_t *ps, char *state)
 {
        char filename[64];
        char f_psinfo[64], f_usage[64];
@@ -1240,9 +1265,9 @@ static int ps_read_process(int pid, procstat_t *ps, char *state)
        psinfo_t *myInfo;
        prusage_t *myUsage;
 
-       snprintf(filename, sizeof (filename), "/proc/%i/status", pid);
-       snprintf(f_psinfo, sizeof (f_psinfo), "/proc/%i/psinfo", pid);
-       snprintf(f_usage, sizeof (f_usage), "/proc/%i/usage", pid);
+       snprintf(filename, sizeof (filename), "/proc/%li/status", pid);
+       snprintf(f_psinfo, sizeof (f_psinfo), "/proc/%li/psinfo", pid);
+       snprintf(f_usage, sizeof (f_usage), "/proc/%li/usage", pid);
 
 
        buffer = malloc(sizeof (pstatus_t));
@@ -1791,7 +1816,7 @@ static int ps_read (void)
        int wait     = 0;
 
        kvm_t *kd;
-       char errbuf[1024];
+       char errbuf[_POSIX2_LINE_MAX];
        struct kinfo_proc *procs;          /* array of processes */
        struct kinfo_proc *proc_ptr = NULL;
        int count;                         /* returns number of processes */
@@ -1803,7 +1828,7 @@ static int ps_read (void)
        ps_list_reset ();
 
        /* Open the kvm interface, get a descriptor */
-       kd = kvm_open (NULL, NULL, NULL, 0, errbuf);
+       kd = kvm_openfiles (NULL, "/dev/null", NULL, 0, errbuf);
        if (kd == NULL)
        {
                ERROR ("processes plugin: Cannot open kvm interface: %s",
@@ -2224,14 +2249,16 @@ static int ps_read (void)
 
        while ((ent = readdir(proc)) != NULL)
        {
-               int pid;
+               long pid;
                struct procstat ps;
                procstat_entry_t pse;
+               char *endptr;
 
                if (!isdigit ((int) ent->d_name[0]))
                        continue;
 
-               if ((pid = atoi (ent->d_name)) < 1)
+               pid = strtol (ent->d_name, &endptr, 10);
+               if (*endptr != 0) /* value didn't completely parse as a number */
                        continue;
 
                status = ps_read_process (pid, &ps, &state);
@@ -2281,8 +2308,7 @@ static int ps_read (void)
 
 
                ps_list_add (ps.name,
-                               ps_get_cmdline ((pid_t) pid,
-                                       cmdline, sizeof (cmdline)),
+                               ps_get_cmdline (pid, cmdline, sizeof (cmdline)),
                                &pse);
        } /* while(readdir) */
        closedir (proc);