Skip Menu |

This queue is for tickets about the Proc-ProcessTable CPAN distribution.

Report information
The Basics
Id: 16978
Status: resolved
Priority: 0/
Queue: Proc-ProcessTable

People
Owner: Nobody in particular
Requestors: cfaber [...] fpsn.net
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: (no value)
Fixed in: (no value)



Subject: Proc::ProcessTable fails to report correct information under FreeBSD 6.0
Running the sample script provided does work, however some fields do not contain useful information, Likely beacuse of a change in the OS: # Dump all the information in the current process table use Proc::ProcessTable; $t = new Proc::ProcessTable; foreach $p (@{$t->table}) { print "--------------------------------\n"; foreach $f ($t->fields){ print $f, ": ", $p->{$f}, "\n"; } } Sample result: -------------------------------- uid: 0 gid: 0 pid: 13 ppid: 0 pgrp: 0 sess: 0 flags: utime: 0.000000 stime: 0.000000 time: 0.000000 wchan: start: 0.000000 euid: 0 egid: 0 fname: idle:\040cpu1 state: ttydev: ttynum: 0 cmndline: idle: cpu1 priority: 0 -------------------------------- uid: 0 gid: 0 pid: 12 ppid: 0 pgrp: 0 sess: 0 flags: utime: 0.000000 stime: 0.000000 time: 0.000000 wchan: start: 0.000000 euid: 0 egid: 0 fname: idle:\040cpu2 state: ttydev: ttynum: 0 cmndline: idle: cpu2 priority: 0 -------------------------------- uid: 0 gid: 0 pid: 11 ppid: 0 pgrp: 0 sess: 0 flags: utime: 0.000000 stime: 0.000000 time: 0.000000 wchan: start: 0.000000 euid: 0 egid: 0 fname: idle:\040cpu3 state: ttydev: ttynum: 0 cmndline: idle: cpu3 priority: 0 -------------------------------- uid: 0 gid: 0 pid: 1 ppid: 0 pgrp: 1 sess: 1 flags: utime: 0.000000 stime: 0.000000 time: 0.000000 wchan: start: 0.000000 euid: 0 egid: 0 fname: init state: ttydev: ttynum: 0 cmndline: /sbin/init -- priority: 0 -------------------------------- uid: 0 gid: 0 pid: 10 ppid: 0 pgrp: 0 sess: 0 flags: utime: 0.000000 stime: 0.000000 time: 0.000000 wchan: start: 0.000000 euid: 0 egid: 0 fname: ktrace state: ttydev: ttynum: 0 cmndline: ktrace priority: 0 -------------------------------- uid: 0 gid: 0 pid: 0 ppid: 0 pgrp: 0 sess: 0 flags: utime: 0.000000 stime: 0.000000 time: 0.000000 wchan: start: 0.000000 euid: 0 egid: 0 fname: swapper state: ttydev: ttynum: 0 cmndline: swapper priority: 0
On Mon Jan 09 12:24:24 2006, guest wrote: Show quoted text
> Running the sample script provided does work, however some fields do > not contain useful information, Likely beacuse of a change in the OS:
[...] Indeed, in FreeBSD 6.0 the format of /proc/.../status changed. Attached are two patches. One is fixing the always broken microsecs calculation, and the second is fixing the changed procfs format, but still retaining the old pre-6.0 implementation. Regards, Slaven
Subject: 0002-FreeBSD-procfs-implementation-FreeBSD-6.0-and-later-.patch
From 712c79f035276249a6e5bc119b9bb6b23ef21f42 Mon Sep 17 00:00:00 2001 From: Slaven Rezic <slaven@rezic.de> Date: Sat, 13 Feb 2010 00:01:31 +0100 Subject: [PATCH 2/2] FreeBSD, procfs implementation: FreeBSD 6.0 and later changed procfs format --- os/FreeBSD.c | 21 +++++++++++++++++++++ os/FreeBSD.h | 12 ++++++++++++ 2 files changed, 33 insertions(+), 0 deletions(-) diff --git a/os/FreeBSD.c b/os/FreeBSD.c index a294b79..a4b2cac 100644 --- a/os/FreeBSD.c +++ b/os/FreeBSD.c @@ -8,14 +8,22 @@ struct procstat* get_procstat( char* path, struct procstat* prs){ if( (fp = fopen( path, "r" )) != NULL ){ fscanf(fp, +#ifdef PROCFS_FREEBSD_6 + "%s %d %d %d %d %s %s %d,%d %d,%d %d,%d %s %d %d %d,%d,%s", +#else "%s %d %d %d %d %d,%d %s %d,%d %d,%d %d,%d %s %d %d %d,%d,%s", +#endif &prs->comm, &prs->pid, &prs->ppid, &prs->pgid, &prs->sid, +#ifdef PROCFS_FREEBSD_6 + &prs->ttydev, +#else &prs->tdev_maj, &prs->tdev_min, +#endif &prs->flags, &prs->start, &prs->start_mic, @@ -93,6 +101,9 @@ void OS_get_table(){ double start_f; char *ttydev; int ttynum; +#ifdef PROCFS_FREEBSD_6 + struct stat tdev_stat; +#endif utime_f = prs.utime + prs.utime_mic/1000000.0; stime_f = prs.stime + prs.stime_mic/1000000.0; @@ -104,9 +115,19 @@ void OS_get_table(){ sprintf(time, "%f", time_f); sprintf(start, "%f", start_f); +#ifdef PROCFS_FREEBSD_6 + ttydev = prs.ttydev; + sprintf(pathbuf, "/dev/%s", ttydev); + if (stat(pathbuf, &tdev_stat) < 0){ + ttynum = -1; + } else { + ttynum = tdev_stat.st_rdev; + } +#else ttynum = makedev(prs.tdev_maj, prs.tdev_min); ttydev = devname(ttynum, S_IFCHR); if (ttydev == NULL) ttydev = "??"; +#endif /* get stuff out of /proc/PROC_ID/cmdline */ sprintf(pathbuf, "%s%s%s", "/proc/", procdirp->d_name, "/cmdline"); diff --git a/os/FreeBSD.h b/os/FreeBSD.h index 85b5117..4b6fca5 100644 --- a/os/FreeBSD.h +++ b/os/FreeBSD.h @@ -11,14 +11,25 @@ #include <stdlib.h> #include <string.h> +#if __FreeBSD_version >= 600000 +/* in FreeBSD 6.x the format of /proc/$pid/status changed */ +#define PROCFS_FREEBSD_6 +#else +#undef PROCFS_FREEBSD_6 +#endif + struct procstat { char comm[MAXCOMLEN+1]; int pid; int ppid; int pgid; int sid; +#ifdef PROCFS_FREEBSD_6 + char ttydev[SPECNAMELEN]; +#else int tdev_maj; int tdev_min; +#endif char flags[256]; /* XXX */ int start; int start_mic; @@ -102,3 +113,4 @@ static char* Fields[] = { #define F_LASTFIELD 19 }; + -- 1.6.4.3
Subject: 0001-FreeBSD-procfs-implementation-fixed-all-fields-with-.patch
From 7e982185411d18fdaf5883ae95b4e5b27240a5cd Mon Sep 17 00:00:00 2001 From: Slaven Rezic <slaven@rezic.de> Date: Sat, 13 Feb 2010 00:00:53 +0100 Subject: [PATCH 1/2] FreeBSD, procfs implementation: fixed all fields with microsecs --- os/FreeBSD.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/os/FreeBSD.c b/os/FreeBSD.c index 08b0919..a294b79 100644 --- a/os/FreeBSD.c +++ b/os/FreeBSD.c @@ -94,10 +94,10 @@ void OS_get_table(){ char *ttydev; int ttynum; - utime_f = prs.utime + prs.utime_mic/1000000; - stime_f = prs.stime + prs.stime_mic/1000000; + utime_f = prs.utime + prs.utime_mic/1000000.0; + stime_f = prs.stime + prs.stime_mic/1000000.0; time_f = utime_f + stime_f; - start_f = prs.start + prs.start_mic/1000000; + start_f = prs.start + prs.start_mic/1000000.0; sprintf(utime, "%f", utime_f); sprintf(stime, "%f", stime_f); -- 1.6.4.3
On Fri Feb 12 18:04:55 2010, SREZIC wrote: Show quoted text
> On Mon Jan 09 12:24:24 2006, guest wrote:
> > Running the sample script provided does work, however some fields do > > not contain useful information, Likely beacuse of a change in the OS:
> [...] > > Indeed, in FreeBSD 6.0 the format of /proc/.../status changed. Attached > are two patches. One is fixing the always broken microsecs calculation, > and the second is fixing the changed procfs format, but still retaining > the old pre-6.0 implementation.
Here's an amendment to the previous patch files. Please use only this one. This patch includes the following changes for FreeBSD: - use kvm implementation as default for FreeBSD 5.x and newer (because procfs is not anymore mounted by default) - fixes in the kvm implementation: - fixed start time if microsecs < 100000 - enhancements in the kvm implementation: - support for user and system time - using FreeBSD-kvm is possible now without any special permissions - fixes in the procfs implementation: - support for FreeBSD 6.x and later - fixed all fields with microsecs Regards, Slaven
Subject: FREEBSD.patch
diff --git c/README.freebsd w/README.freebsd deleted file mode 100644 index 4da4431..0000000 --- c/README.freebsd +++ /dev/null @@ -1,23 +0,0 @@ -SUPPORTED ATTRIBUTES -==================== - uid UID of process - gid GID of process - euid effective UID of process - egid effective GID of process - pid process ID - ppid parent process ID - pgrp process group - sess session ID - priority priority of process - ttynum tty number of process - flags flags of process - utime user mode time - stime kernel mode time - time user + system time - wchan address of current system call - fname file name - start start time (seconds since the epoch) - state state of process - ttydev path of process's tty - cmndline full command line of process - priority priority of process diff --git c/README.freebsd-kvm w/README.freebsd-kvm index 470f161..4c0ec09 100644 --- c/README.freebsd-kvm +++ w/README.freebsd-kvm @@ -12,6 +12,8 @@ SUPPORTED ATTRIBUTES sflags PS_* flags start start time time running time (in seconds) + utime user time (in seconds) + stime system time (in seconds) wchan current system call state state of process @@ -36,8 +38,6 @@ its use is not recommended in future. In addition, mapping processes space to /proc is not correct (at least, in 7 of 7 my freebsd servers with FreeBSD5 installed). -So, I decided to write this code. This module works via kvm system, all its -need is access to /dev/mem and /dev/kmem (you can add user to kmem group -in /etc/groups file). +So, I decided to write this code. This module works via the kvm system. Any comments please send to king2@kaluga.ru. diff --git c/README.freebsd-procfs w/README.freebsd-procfs new file mode 100644 index 0000000..4da4431 --- /dev/null +++ w/README.freebsd-procfs @@ -0,0 +1,23 @@ +SUPPORTED ATTRIBUTES +==================== + uid UID of process + gid GID of process + euid effective UID of process + egid effective GID of process + pid process ID + ppid parent process ID + pgrp process group + sess session ID + priority priority of process + ttynum tty number of process + flags flags of process + utime user mode time + stime kernel mode time + time user + system time + wchan address of current system call + fname file name + start start time (seconds since the epoch) + state state of process + ttydev path of process's tty + cmndline full command line of process + priority priority of process diff --git c/hints/freebsd.pl w/hints/freebsd.pl old mode 100644 new mode 100755 index 28a5b27..a18a0be --- c/hints/freebsd.pl +++ w/hints/freebsd.pl @@ -1 +1,11 @@ -symlink "os/FreeBSD.c", "OS.c" || die "Could not link os/FreeBSD.c to os/OS.c\n"; +require Config; +my($maj) = $Config::Config{osvers} =~ m{^(\d+)}; +if ($maj < 5) { + print STDERR "Using procfs implementation\n"; + symlink "os/FreeBSD.c", "OS.c" || die "Could not link os/FreeBSD.c to os/OS.c\n"; +} else { + print STDERR "Using kvm implementation\n"; + symlink "os/FreeBSD-kvm.c", "OS.c" || die "Could not link os/FreeBSD-kvm.c to os/OS.c\n"; + $self->{LIBS} = ['-lkvm']; +} + diff --git c/hints/freebsd_5.pl w/hints/freebsd_5.pl deleted file mode 100644 index aeee53b..0000000 --- c/hints/freebsd_5.pl +++ /dev/null @@ -1,2 +0,0 @@ -symlink "os/FreeBSD-kvm.c", "OS.c" || die "Could not link os/FreeBSD-kvm.c to os/OS.c\n"; -$self->{LIBS} = ['-lkvm']; diff --git c/os/FreeBSD-kvm.c w/os/FreeBSD-kvm.c index bc7f6f6..43c2611 100644 --- c/os/FreeBSD-kvm.c +++ w/os/FreeBSD-kvm.c @@ -2,8 +2,11 @@ #include <unistd.h> #include <sys/sysctl.h> #include <sys/proc.h> +#include <sys/times.h> #include <sys/user.h> +#include <fcntl.h> #include <kvm.h> +#include <paths.h> @@ -24,6 +27,8 @@ void OS_get_table(){ char state[20]; char start[20]; char time[20]; + char utime[20]; + char stime[20]; char flag[20]; char sflag[20]; @@ -32,7 +37,7 @@ void OS_get_table(){ int priority; /* Open the kvm interface, get a descriptor */ - if ((kd = kvm_open(NULL, NULL, NULL, 0, errbuf)) == NULL) { + if ((kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf)) == NULL) { fprintf(stderr, "kvm_open: %s\n", errbuf); ppt_croak("kvm_open: ", errbuf); } @@ -92,8 +97,10 @@ void OS_get_table(){ } - sprintf(start, "%d.%d", procs[i].ki_start.tv_sec, procs[i].ki_start.tv_usec); + sprintf(start, "%d.%06d", procs[i].ki_start.tv_sec, procs[i].ki_start.tv_usec); sprintf(time, "%.6f", procs[i].ki_runtime/1000000.0); + sprintf(utime, "%d.%06d", procs[i].ki_rusage.ru_utime.tv_sec, procs[i].ki_rusage.ru_utime.tv_usec); + sprintf(stime, "%d.%06d", procs[i].ki_rusage.ru_stime.tv_sec, procs[i].ki_rusage.ru_stime.tv_usec); sprintf(flag, "0x%04x", procs[i].ki_flag); sprintf(sflag, "0x%04x", procs[i].ki_sflag); @@ -113,6 +120,8 @@ void OS_get_table(){ start, time, + utime, + stime, procs[i].ki_wmesg, state, diff --git c/os/FreeBSD-kvm.h w/os/FreeBSD-kvm.h index bda9364..ca16153 100644 --- c/os/FreeBSD-kvm.h +++ w/os/FreeBSD-kvm.h @@ -13,7 +13,7 @@ /* We need to pass in a cap for ignore, lower for store on object */ /* We can just lc these! */ -static char Defaultformat[] = "iiiiiiisssssssissiiiiiii"; +static char Defaultformat[] = "iiiiiiisssssssssissiiiiiii"; /* Mapping of field to type */ static char* Fields[] = { @@ -29,6 +29,8 @@ static char* Fields[] = { "sflags", "start", "time", + "utime", + "stime", "wchan", "state", diff --git c/os/FreeBSD.c w/os/FreeBSD.c index 08b0919..a4b2cac 100644 --- c/os/FreeBSD.c +++ w/os/FreeBSD.c @@ -8,14 +8,22 @@ struct procstat* get_procstat( char* path, struct procstat* prs){ if( (fp = fopen( path, "r" )) != NULL ){ fscanf(fp, +#ifdef PROCFS_FREEBSD_6 + "%s %d %d %d %d %s %s %d,%d %d,%d %d,%d %s %d %d %d,%d,%s", +#else "%s %d %d %d %d %d,%d %s %d,%d %d,%d %d,%d %s %d %d %d,%d,%s", +#endif &prs->comm, &prs->pid, &prs->ppid, &prs->pgid, &prs->sid, +#ifdef PROCFS_FREEBSD_6 + &prs->ttydev, +#else &prs->tdev_maj, &prs->tdev_min, +#endif &prs->flags, &prs->start, &prs->start_mic, @@ -93,20 +101,33 @@ void OS_get_table(){ double start_f; char *ttydev; int ttynum; +#ifdef PROCFS_FREEBSD_6 + struct stat tdev_stat; +#endif - utime_f = prs.utime + prs.utime_mic/1000000; - stime_f = prs.stime + prs.stime_mic/1000000; + utime_f = prs.utime + prs.utime_mic/1000000.0; + stime_f = prs.stime + prs.stime_mic/1000000.0; time_f = utime_f + stime_f; - start_f = prs.start + prs.start_mic/1000000; + start_f = prs.start + prs.start_mic/1000000.0; sprintf(utime, "%f", utime_f); sprintf(stime, "%f", stime_f); sprintf(time, "%f", time_f); sprintf(start, "%f", start_f); +#ifdef PROCFS_FREEBSD_6 + ttydev = prs.ttydev; + sprintf(pathbuf, "/dev/%s", ttydev); + if (stat(pathbuf, &tdev_stat) < 0){ + ttynum = -1; + } else { + ttynum = tdev_stat.st_rdev; + } +#else ttynum = makedev(prs.tdev_maj, prs.tdev_min); ttydev = devname(ttynum, S_IFCHR); if (ttydev == NULL) ttydev = "??"; +#endif /* get stuff out of /proc/PROC_ID/cmdline */ sprintf(pathbuf, "%s%s%s", "/proc/", procdirp->d_name, "/cmdline"); diff --git c/os/FreeBSD.h w/os/FreeBSD.h index 85b5117..4b6fca5 100644 --- c/os/FreeBSD.h +++ w/os/FreeBSD.h @@ -11,14 +11,25 @@ #include <stdlib.h> #include <string.h> +#if __FreeBSD_version >= 600000 +/* in FreeBSD 6.x the format of /proc/$pid/status changed */ +#define PROCFS_FREEBSD_6 +#else +#undef PROCFS_FREEBSD_6 +#endif + struct procstat { char comm[MAXCOMLEN+1]; int pid; int ppid; int pgid; int sid; +#ifdef PROCFS_FREEBSD_6 + char ttydev[SPECNAMELEN]; +#else int tdev_maj; int tdev_min; +#endif char flags[256]; /* XXX */ int start; int start_mic; @@ -102,3 +113,4 @@ static char* Fields[] = { #define F_LASTFIELD 19 }; +
On 2010-02-12 18:55:49, SREZIC wrote: Show quoted text
> On Fri Feb 12 18:04:55 2010, SREZIC wrote:
> > On Mon Jan 09 12:24:24 2006, guest wrote:
> > > Running the sample script provided does work, however some fields do > > > not contain useful information, Likely beacuse of a change in the OS:
> > [...] > > > > Indeed, in FreeBSD 6.0 the format of /proc/.../status changed. Attached > > are two patches. One is fixing the always broken microsecs calculation, > > and the second is fixing the changed procfs format, but still retaining > > the old pre-6.0 implementation.
> > Here's an amendment to the previous patch files. Please use only this > one. This patch includes the following changes for FreeBSD: > - use kvm implementation as default for FreeBSD 5.x and newer (because > procfs is not anymore mounted by default) > - fixes in the kvm implementation: > - fixed start time if microsecs < 100000 > - enhancements in the kvm implementation: > - support for user and system time > - using FreeBSD-kvm is possible now without any special permissions > - fixes in the procfs implementation: > - support for FreeBSD 6.x and later > - fixed all fields with microsecs >
This patch is still fine with Proc-ProcessTable 0.46 and works for recent FreeBSD versions (e.g. 8.0 and 9.0). Regards, Slaven
closed in v0.47