Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Use the /proc filesystem on cygwin #7

Merged
merged 1 commit into from

2 participants

@mithun

Cygwin provides a working /proc filesystem that is pretty similar to
Linux distributions. P9Y::ProcessTable::Win32 is updated to recognize
when running on Cygwin and provide the following behavior:

  • Use the /proc filesystem to provide Cygwin process info
  • Use Win32::Process::Info to provide Windows process info

This provides the user with both Cygwin and Windows processes
when on cygwin and only Windows processes when on Win32.

@SineSwiper
Owner

You have a bunch of space changes everywhere. Can you clean that up? (Three spaces, please, or vertical alignment when needed/desired.)

Also, I'm not sure about the win* properties in ::Process. The whole point of P9Y::PT is normalization of this stuff between OSs. What is the specific need for both pids?

@mithun

You have a bunch of space changes everywhere. Can you clean that up? (Three spaces, please, or vertical alignment when needed/desired.)

I usually run code through perltidy. Of course, this is currently setup to my preference. If you have a perltidy config you'd like me to use please let me know. Otherwise I can go thru' and manually fix the indentation.

Also, I'm not sure about the win* properties in ::Process. The whole point of P9Y::PT is normalization of this stuff between OSs. What is the specific need for both pids?

When running under cygwin, both cygwin and Windows assign their own PIDs to the same process - perlcygwin. Under some conditions, users will need either the cygwin pid or windows pid or both. The win* properties are also exposed by Proc::PT under cygwin, so this will help users easily migrate to using P9Y::PT.

@mithun

Fixed indentation to use 3 spaces.

@mithun mithun Use the /proc filesystem on cygwin
Cygwin provides a working /proc filesystem that is pretty similar to
Linux distributions. P9Y::ProcessTable::Win32 is updated to recognize
when running on Cygwin and provide the following behavior:

- Use the /proc filesystem to provide Cygwin process info
- Use Win32::Process::Info to provide Windows process info

This provides the user with both Cygwin and Windows processes
when on cygwin and only Windows processes when on Win32.
9b51815
@SineSwiper
Owner

Well, if P:PT already has it, then I'm cool with using it.

@SineSwiper SineSwiper merged commit 028a5d6 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 26, 2013
  1. @mithun

    Use the /proc filesystem on cygwin

    mithun authored mithun committed
    Cygwin provides a working /proc filesystem that is pretty similar to
    Linux distributions. P9Y::ProcessTable::Win32 is updated to recognize
    when running on Cygwin and provide the following behavior:
    
    - Use the /proc filesystem to provide Cygwin process info
    - Use Win32::Process::Info to provide Windows process info
    
    This provides the user with both Cygwin and Windows processes
    when on cygwin and only Windows processes when on Win32.
This page is out of date. Refresh to see the latest.
Showing with 176 additions and 29 deletions.
  1. +3 −0  lib/P9Y/ProcessTable/Process.pm
  2. +173 −29 lib/P9Y/ProcessTable/Win32.pm
View
3  lib/P9Y/ProcessTable/Process.pm
@@ -74,6 +74,9 @@ has cpuid => ( is => 'rwp', predicate => 1 );
has pctcpu => ( is => 'rwp', predicate => 1 );
has pctmem => ( is => 'rwp', predicate => 1 );
+has winpid => ( is => 'rwp', predicate => 1 );
+has winexe => ( is => 'rwp', predicate => 1 );
+
#sub fields {
# return ( qw/
# pid uid gid euid egid suid sgid ppid pgrp sess
View
202 lib/P9Y/ProcessTable/Win32.pm
@@ -23,28 +23,33 @@ no warnings 'uninitialized';
my $pi = Win32::Process::Info->new();
+my $IS_CYGWIN = ($^O =~ /cygwin/i) ? 1 : 0;
+
#############################################################################
# Methods
no warnings 'redefine';
+
sub list {
- my $self = shift;
- return sort { $a <=> $b } ($pi->ListPids);
+ my %winpids = map { $_ => 1 } _win32_list();
+ my %cygpids = map { $_ => 1 } ($IS_CYGWIN ? _cyg_list() : ());
+ my %pids = (%winpids, %cygpids,);
+ return sort { $a <=> $b } keys %pids;
}
+
sub fields {
- return ( qw/
- pid uid ppid sess
- exe root
- ttlflt utime stime start state time
- threads priority fname state size rss
- / );
+ my %winflds = map { $_ => 1 } _win32_fields();
+ my %cygflds = map { $_ => 1 } ($IS_CYGWIN ? _cyg_fields() : ());
+ my %fields = (%winflds, %cygflds,);
+ return sort { lc $a cmp lc $b } keys %fields;
}
+
sub process {
my ($self, $pid) = @_;
- $pid = Win32::Process::GetCurrentProcessID if (@_ == 1); # process() changed here...
+ $pid = $$ unless defined $pid;
my $hash = $self->_process_hash($pid);
return unless $hash && $hash->{pid} && $hash->{ppid};
@@ -52,44 +57,183 @@ sub process {
return P9Y::ProcessTable::Process->new($hash);
}
+
sub _process_hash {
my ($self, $pid) = @_;
+
+ my $hash = {};
+ if ($IS_CYGWIN and Cygwin::pid_to_winpid($pid)) {
+ $hash = _cyg_process_hash($pid);
+ }
+ else {
+ $hash = _win32_process_hash($pid);
+ }
+
+ return $hash;
+}
+
+############################
+## Win32 only methods
+
+
+sub _win32_list {
+ return sort { $a <=> $b } ($pi->ListPids);
+}
+
+
+sub _win32_fields {
+ return (
+ qw/
+ pid uid ppid sess
+ exe root
+ ttlflt utime stime start state time
+ threads priority fname state size rss
+ /
+ );
+}
+
+
+sub _win32_process_hash {
+ my ($pid) = @_;
my $info = $pi->GetProcInfo($pid);
return unless $info;
$info = $info->[0];
- my $hash = {};
- my $stat_loc = { qw/
- pid ProcessId
- uid Owner
- ppid ParentProcessId
- sess SessionId
- exe ExecutablePath
- threads ThreadCount
- priority Priority
- ttlflt PageFaults
- utime UserModeTime
- stime KernelModeTime
- size VirtualSize
- rss WorkingSetSize
- fname Caption
- start CreationDate
- state Status
- cmdline CommandLine
- / };
+ my $hash = {};
+ my $stat_loc = {
+ qw/
+ pid ProcessId
+ uid Owner
+ ppid ParentProcessId
+ sess SessionId
+ exe ExecutablePath
+ threads ThreadCount
+ priority Priority
+ ttlflt PageFaults
+ utime UserModeTime
+ stime KernelModeTime
+ size VirtualSize
+ rss WorkingSetSize
+ fname Caption
+ start CreationDate
+ state Status
+ cmdline CommandLine
+ /
+ };
foreach my $key (keys %$stat_loc) {
my $item = $info->{ $stat_loc->{$key} };
$hash->{$key} = $item if defined $item;
}
- $hash->{exe} =~ /^(\w\:\\)/;
+ $hash->{exe} =~ /^(\w\:\\)/;
$hash->{root} = $1;
$hash->{time} = $hash->{utime} + $hash->{stime};
return $hash;
}
+############################
+## Cygwin only methods
+
+
+sub _cyg_list {
+ my @list;
+
+ my $dir = dir('', 'proc');
+ while (my $pdir = $dir->next) {
+ next unless ($pdir->is_dir);
+ next unless (-e $pdir->file('status'));
+ next unless ($pdir->basename =~ /^\d+$/);
+
+ push @list, $pdir->basename;
+ }
+
+ return @list;
+}
+
+
+sub _cyg_fields {
+ return qw(
+ pid uid gid ppid pgrp sess
+ cwd exe root cmdline
+ minflt cminflt majflt cmajflt ttlflt cttlflt
+ utime stime cutime cstime start time ctime
+ priority fname state ttynum flags size rss
+ winpid winexe
+ );
+}
+
+
+sub _cyg_process_hash {
+ my ($pid) = @_;
+
+ my $pdir = dir('', 'proc', $pid);
+ return unless (-d $pdir);
+ my $hash = {
+ pid => $pid,
+ uid => $pdir->stat->uid,
+ gid => $pdir->stat->gid,
+ start => $pdir->stat->mtime,
+ };
+
+ # process links
+ foreach my $ln (qw{cwd exe root}) {
+ my $link = $pdir->file($ln);
+ $hash->{$ln} = readlink $link if (-l $link);
+ }
+
+ # process simple cats
+ foreach my $fn (qw{cmdline winpid winexename}) {
+ my $file = $pdir->file($fn);
+ $hash->{$fn} = $file->slurp if (-f $file);
+ $hash->{$fn} =~ s/\0/ /g;
+ $hash->{$fn} =~ s/^\s+|\s+$//g;
+ $hash->{winexe} = $hash->{$fn} if ($fn eq 'winexename');
+ }
+
+ # process main PID stats
+ if (-f $pdir->file('stat')) {
+
+ # stat
+ my $data = $pdir->file('stat')->slurp;
+ my @data = split /\s+/, $data;
+
+ my $states = {
+ R => 'run',
+ S => 'sleep',
+ D => 'disk sleep',
+ Z => 'defunct',
+ T => 'stop',
+ W => 'paging',
+ };
+
+ # See cygwin/fhandler_process.cc for the order
+ my $stat_loc = [
+ qw(
+ pid fname state ppid pgrp sess ttynum . flags minflt cminflt majflt cmajflt
+ utime stime cutime cstime priority . . . . size rss .
+ )
+ ];
+
+ foreach my $i (0 .. @data - 1) {
+ next if $stat_loc->[$i] eq '.';
+ last if ($i >= @$stat_loc);
+ $hash->{ $stat_loc->[$i] } = $data[$i];
+ }
+
+ $hash->{fname} =~ s/^\((.+)\)$/$1/;
+ $hash->{state} = $states->{ $hash->{state} };
+ $hash->{time} = $hash->{utime} + $hash->{stime};
+ $hash->{ctime} = $hash->{cutime} + $hash->{cstime};
+
+ $hash->{ttlflt} = $hash->{minflt} + $hash->{majflt};
+ $hash->{cttlflt} = $hash->{cminflt} + $hash->{cmajflt};
+ }
+
+ return $hash;
+}
+
#############################################################################
# Process side
Something went wrong with that request. Please try again.