Skip Menu |

This queue is for tickets about the Win32-Process-Info CPAN distribution.

Report information
The Basics
Id: 35931
Status: stalled
Priority: 0/
Queue: Win32-Process-Info

People
Owner: Nobody in particular
Requestors: KES [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 1.011
Fixed in: (no value)



Subject: Programm crashes while using Win32::Process::Info
Programm need to work 24 hours 7 days per week but it can not... it crashes after 5-6 hours =( I am calculating memory usage and this code is runned every 5 seconds The daemon runned as service with help of module: Win32::Daemon sub updateMemoryUsageStat { my( $context )= @_; my $pi = Win32::Process::Info->new(); foreach my $task ( @{ $context->{tasks} } ) { my $usage= { VirtualPeak => 0, PhysicalPeak => 0, }; my $children= $pi->Subprocesses( $task->{PID} ); my @procList= subprocessesList( $task->{PID}, $children ); my @procsInfo= $pi->GetProcInfo( @procList ); for my $procInfo ( @procsInfo ) { $usage->{VirtualPeak}+= $procInfo->{PeakVirtualSize}; $usage->{PhysicalPeak}+= $procInfo->{PeakWorkingSetSize}; } $usage->{VirtualPeak}/=1024*1024; $usage->{PhysicalPeak}/=1024*1024; } sub subprocessesList { my( $currPid, $children )= @_; my @processes= ( $currPid ); foreach my $pid ( @{ $children->{$currPid} } ) { push @processes, subprocessesList( $pid, $children ); } return @processes; } sub Callback_Running { my( $event, $context ) = @_; #if( SERVICE_RUNNING == Win32::Daemon::State() ) {#Perl 5.8 if( $event == 4128 ) { #Perl 5.10 updateMemoryUsageStat( $context ); } return undef; }
Win32::Process::Info has three possible 'back ends' to gather its information. The default is 'WMI', for historical reasons. But this is known to leak memory because of unresolved problems in Win32::OLE, and I recommend that the 'WMI' variant not be used for daemons. Unfortunately, the 'NT' variant does not return the information you want. Under the assumption that the problem is memory leaking from Win32::OLE, the problem can be minimized (but NOT eliminated) by changing your my @procsInfo= $pi->GetProcInfo( @procList ); to my @procsInfo= $pi->GetProcInfo( {no_user_info => 1}, @procList ); If the problem is that Win32::OLE leaks memory then this will still crash eventually, but maybe it will run long enough. It prevents the username and SID from being returned, but your script does not appear to use these, and that is where the worst leakage is. Since I have no control over Win32::OLE, this may end up being turned into an enhancement request to add the information you need to the 'NT' variant. I am not sure how quickly this can be responded to, since I am not in the position to do Windows development that I was when this module was written. The first step would be a documentation search to see if there is a documented source for these other than WMI -- there was not when I wrote the module. Please let me know whether the recommended change affects the problem.
I modify my code in next way: I create $pi object only once when service is started then reuse it: sub Callback_Start { my( $event, $context ) = @_; ... $context->{ProcInfo} = Win32::Process::Info->new(); ... } Then I add logging to my subroutine: sub updateMemoryUsageStat { my( $context )= @_; foreach my $task ( @{ $context->{tasks} } ) { my $usage= { VirtualPeak => 0, PhysicalPeak => 0, }; msgLog( $context->{logFile}, localtime(). " START" ) if $DEBUG >= 5; my $children= $context->{ProcInfo}->Subprocesses( $task->{PID} ); msgLog( $context->{logFile}, localtime(). " Subprocesses completed" ) if $DEBUG >= 5; my @procList= subprocessesList( $task->{PID}, $children ); msgLog( $context->{logFile}, localtime(). " List completed" ) if $DEBUG >= 5; my @procsInfo= $context->{ProcInfo}->GetProcInfo( @procList ); msgLog( $context->{logFile}, localtime(). " ProcInfo completed" ) if $DEBUG >= 5; msgLog( $context->{logFile}, localtime(). Dumper( @procsInfo ) ) if $DEBUG >= 5; for my $procInfo ( @procsInfo ) { $usage->{VirtualPeak}+= $procInfo->{PeakVirtualSize}; $usage->{PhysicalPeak}+= $procInfo->{PeakWorkingSetSize}; } $usage->{VirtualPeak}/=1024*1024; $usage->{PhysicalPeak}/=1024*1024; } Now daemon runs longer but also crashes (( It crashes while calling to 'Subprocesses' and not to GetProcInfo Any sugggestions?
On Mon May 19 08:55:55 2008, KES wrote: <snip /> Show quoted text
> > Now daemon runs longer but also crashes (( > It crashes while calling to 'Subprocesses' and not to GetProcInfo > > Any sugggestions?
None of the sort you would really want to hear, or that I would want to give you. I would like to recommend that you move to the NT variant, but unfortunately only the WMI variant gives you the data you need. I am not in a position to enhance the NT variant at the moment, nor am I able to make the WMI variant more reliable since the problem is in Win32::OLE. All I can think of is either to try to live with the problem, or look into one of the other packages under "RELATED MODULES" in the documentation. I have not looked at any of these recently, but memory says that Win32::PerfLib is more likely to have the memory usage; whether it has the subprocesses I do not remember, but I _do_ remember that the interface looks like a pain. If I were to try to live with the limitations to Win32::Process::Info, I think I would try to find a way to get it restarted periodically, preserving the information you had gathered. I would probably use YAML for a little data, or YAML::Syck for a lot, but Storable and Data::Dumper are reasonable alternatives. A reasonably modern Windows will restart a failed service if you request this, so a cheap alternative would be just to detect when the service has been running long enough (say, two hours), have it dump its data and then die. When Windows restarts the service it can reload the dumped data and resume its function. The question here is how long it will take Windows to notice that the service has died. If it is too long, I might try making the service into a watchdog that spawns the data collection code into a subprocess, watches for its exit using the Win32::Process module, and restarts it. My apologies for not having a better response for you. Tom Wyant
I think I would live with it. Now I spawn new process from service and do all job there. Service just check child to exist and respawn it when it dies. Seems this fit all problem I want to resolve Thx for support. hope it will be fixed. bye
Because I can not do anything about the Win32::OLE behaviour, I am going to change this to a "wishlist" item. My intent, eventually, is to try to add the desired functionality to the "NT" variant, which avoids the OLE weirdness. I am also going to mark it "Stalled", until I acquire a means to work on it. Sorry not to have a better answer.