# hlida zmeny nastaveni 'watchdog-setting.bin' # hlida vystup programu presmerovany do souboru use strict; use File::stat; use Time::HiRes qw(sleep); use Storable; use Data::Dump qw(dump); use Win32::Process::Info; # default my $timeout_to_kill = 3*60; my $sleep_between_checks = 10; sub kill_inside { my ( $pid ) = @_; print "trying to find and kill one child (parent pid: $pid)\n"; my $pi = Win32::Process::Info->new(); my %subs = $pi->Subprocesses(); # Figure out subprocess relationships. if (0) { open FP, ">>$0.pids"; my @pids = $pi->ListPids (); # Get all known PIDs my @info = $pi->GetProcInfo (); # Get the max my %subs = $pi->Subprocesses(); # Figure out subprocess relationships. print FP dump( \@pids ) . "\n---\n\n";; print FP dump( \@info ) . "\n---\n\n";; print FP dump( \%subs ) . "\n---\n\n"; print FP dump( $subs{$pid} ); close FP; print "pid log saved\n"; } my @childs = @{ $subs{$pid} }; my $to_kill = $pid; # go deep while ( (exists $subs{$to_kill}) && (scalar @{ $subs{$to_kill} }) ) { $to_kill = $subs{$to_kill}->[-1]; } print "found pid $to_kill\n"; unless ( kill( 'INT', $to_kill ) ) { return kill( 9, $to_kill ); } return 1; } my ( $st, $mtime, $diff ); my $ipc_fn = 'watchdog-setting.bin'; my $text = ''; my ( $o_text, $ch_time, $mch_time ); $ch_time = time(); $mch_time = $ch_time; my $last_ff_time; my $same_num = 0; my $prev_pid = 0; my $pid = 0; my $prev_fn = ''; my $fn = ''; while (1) { while ( -f $ipc_fn ) { my $info = retrieve($ipc_fn) or die "$!\n$@"; # print dump( $info ) . "\n"; if ( exists $info->{'timeout'} ) { $timeout_to_kill = $info->{'timeout'}; if ( exists $info->{'sleep'} ) { $sleep_between_checks = $info->{'sleep'}; } else { $sleep_between_checks = int($timeout_to_kill/5)+1; } } $prev_fn = $fn; $fn = $info->{'log_fn'}; if ( $prev_fn ne $fn ) { print "new process log file (fn: $fn)\n"; $mch_time = $ch_time; $ch_time = time(); $same_num = 0; } $prev_pid = $pid; $pid = $info->{'pid'}; if ( $prev_pid != $pid ) { print "new process (pid: $pid)\n"; $mch_time = $ch_time; $ch_time = time(); $same_num = 0; } open ( LOG, $fn ) or die "$fn $!$@"; $o_text = $text; { local $/ = undef; $text = ; } close LOG; my $diff = time() - $ch_time; my $n_diff = $diff - $timeout_to_kill; if ( $o_text ne $text ) { $mch_time = $ch_time; $ch_time = time(); my $a_diff = $ch_time - $mch_time; print "changed after $a_diff s (reserve:$n_diff, timeout:$timeout_to_kill)\n"; $same_num = 0; } else { $same_num++; if ( $diff > $timeout_to_kill ) { print "error, not changed for $diff s (reserve:$n_diff, timeout:$timeout_to_kill)\n"; my $res = kill_inside( $pid ); if ( $res ) { print "pid: child pid was killed\n"; $same_num = 0; $mch_time = $ch_time; $ch_time = time(); print "child for pid $pid killed\n"; $same_num = 0; } else { print "pid: $pid wasn't killed\n"; } } elsif ( $diff > 0 ) { print "same for $diff s (reserve:$n_diff, timeout:$timeout_to_kill, same_num:$same_num)\n"; } } sleep( $sleep_between_checks ); $last_ff_time = time(); } print "'$ipc_fn' not found " . ( defined $last_ff_time ? 'for ' .( time()-$last_ff_time ) . ' s' : '' ) . "\n"; sleep $sleep_between_checks; }