Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the /proc filesystem on cygwin #7

Merged
merged 1 commit into from Feb 27, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/P9Y/ProcessTable/Process.pm
Expand Up @@ -74,6 +74,9 @@ has cpuid => ( is => 'rwp', predicate => 1 );
has pctcpu => ( is => 'rwp', predicate => 1 ); has pctcpu => ( is => 'rwp', predicate => 1 );
has pctmem => ( is => 'rwp', predicate => 1 ); has pctmem => ( is => 'rwp', predicate => 1 );


has winpid => ( is => 'rwp', predicate => 1 );
has winexe => ( is => 'rwp', predicate => 1 );

#sub fields { #sub fields {
# return ( qw/ # return ( qw/
# pid uid gid euid egid suid sgid ppid pgrp sess # pid uid gid euid egid suid sgid ppid pgrp sess
Expand Down
202 changes: 173 additions & 29 deletions lib/P9Y/ProcessTable/Win32.pm
Expand Up @@ -23,73 +23,217 @@ no warnings 'uninitialized';


my $pi = Win32::Process::Info->new(); my $pi = Win32::Process::Info->new();


my $IS_CYGWIN = ($^O =~ /cygwin/i) ? 1 : 0;

############################################################################# #############################################################################
# Methods # Methods


no warnings 'redefine'; no warnings 'redefine';



sub list { sub list {
my $self = shift; my %winpids = map { $_ => 1 } _win32_list();
return sort { $a <=> $b } ($pi->ListPids); my %cygpids = map { $_ => 1 } ($IS_CYGWIN ? _cyg_list() : ());
my %pids = (%winpids, %cygpids,);
return sort { $a <=> $b } keys %pids;
} }



sub fields { sub fields {
return ( qw/ my %winflds = map { $_ => 1 } _win32_fields();
pid uid ppid sess my %cygflds = map { $_ => 1 } ($IS_CYGWIN ? _cyg_fields() : ());
exe root my %fields = (%winflds, %cygflds,);
ttlflt utime stime start state time return sort { lc $a cmp lc $b } keys %fields;
threads priority fname state size rss
/ );
} }



sub process { sub process {
my ($self, $pid) = @_; my ($self, $pid) = @_;
$pid = Win32::Process::GetCurrentProcessID if (@_ == 1); # process() changed here... $pid = $$ unless defined $pid;
my $hash = $self->_process_hash($pid); my $hash = $self->_process_hash($pid);
return unless $hash && $hash->{pid} && $hash->{ppid}; return unless $hash && $hash->{pid} && $hash->{ppid};


$hash->{_pt_obj} = $self; $hash->{_pt_obj} = $self;
return P9Y::ProcessTable::Process->new($hash); return P9Y::ProcessTable::Process->new($hash);
} }



sub _process_hash { sub _process_hash {
my ($self, $pid) = @_; 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); my $info = $pi->GetProcInfo($pid);
return unless $info; return unless $info;
$info = $info->[0]; $info = $info->[0];


my $hash = {}; my $hash = {};
my $stat_loc = { qw/ my $stat_loc = {
pid ProcessId qw/
uid Owner pid ProcessId
ppid ParentProcessId uid Owner
sess SessionId ppid ParentProcessId
exe ExecutablePath sess SessionId
threads ThreadCount exe ExecutablePath
priority Priority threads ThreadCount
ttlflt PageFaults priority Priority
utime UserModeTime ttlflt PageFaults
stime KernelModeTime utime UserModeTime
size VirtualSize stime KernelModeTime
rss WorkingSetSize size VirtualSize
fname Caption rss WorkingSetSize
start CreationDate fname Caption
state Status start CreationDate
cmdline CommandLine state Status
/ }; cmdline CommandLine
/
};


foreach my $key (keys %$stat_loc) { foreach my $key (keys %$stat_loc) {
my $item = $info->{ $stat_loc->{$key} }; my $item = $info->{ $stat_loc->{$key} };
$hash->{$key} = $item if defined $item; $hash->{$key} = $item if defined $item;
} }


$hash->{exe} =~ /^(\w\:\\)/; $hash->{exe} =~ /^(\w\:\\)/;
$hash->{root} = $1; $hash->{root} = $1;
$hash->{time} = $hash->{utime} + $hash->{stime}; $hash->{time} = $hash->{utime} + $hash->{stime};


return $hash; 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 # Process side


Expand Down