Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

Re: Backticks and SIGALRM

by jbert (Priest)
on Aug 20, 2007 at 13:23 UTC ( #633816=note: print w/replies, xml ) Need Help??

in reply to Backticks and SIGALRM

Your code appears to work here (ubuntu linux, perl 5.8.8).

This is using backticks (not a system call, as you have in your code. All I did was to replace the extApp $_ with sleep 5.

Can you give some info on your platform and perl version please, and also let us know what the following script prints on your system?

#!/usr/bin/perl use strict; use warnings; my @result; $SIG{ALRM} = sub { print "ALARM fired\n"; die "timeout"; }; eval { alarm(3); @result = `sleep 5`; alarm(0); }; print "Running after alarm: $@\n"; if ($@) { if ($@ =~ /timeout/i) { push @result, "App has hanged itself\n"; } else { alarm(0); # clear the still-pending alarm die; # propagate unexpected exception } } print "result is: ", join('', @result), "\n";
I get:
ALARM fired Running after alarm: timeout at line 8. result is: App has hanged itself
On a side note, when you propagate the 'die' error, it's best to re-throw the original die object/text with die $@ to give higher-level code a chance of working out what went wrong.

Replies are listed 'Best First'.
Re^2: Backticks and SIGALRM
by nemo (Sexton) on Aug 20, 2007 at 13:30 UTC
    Hi Jbert,
    I haven't tested your code but it will work correctly, I tested the alarm code before with Inifinite loops and it works as expected. The problem is the hanging app in the shell. I am running on MSWIN32-x86-multi-thread Perl version 5.8.8.

    Thank you for your replies.
      Ah, OK. So you want to be able to kill off the offending sub-process when the alarm fires? Then you either need to walk the process table, looking for a process whose parent is your script, or start the process in a way which allows you to get the pid and the output.

      e.g. run the code under a piped open, something like this (untested):

      my $cmd = "your command"; my $pid = open(my $fh, "$cmd|"); $SIG{ALRM} = sub { print "Alarm fired, killing pid $pid\n"; # Replace with windows-specific code to kill process kill 15, $pid; }; die "Can't run command [$cmd] : $!" unless $pid; # Or do some other processing with $fh push @result, $_ while (<$fh>); close $fh or die "Problem running [$cmd] : $?";
      If your child process starts yet more children (and they don't exit when the parent is killed), you'll have to write more elaborate cleanup code.

      Dig through the windows-related process modules on CPAN and you should find what you need for the cleanup.

        Just a minor pick (which applies to all posted solutions so far) , on unixlike the killing part should be in at least two stages: first send signal of normal termination (SIGTERM) and then signal of immediate termination (SIGKILL) to let the ext. app a chance to clean up. In some cases even stop/cont signals can be appropriate. It is probably better to send signal to the process group id (perl kill with negative signal, or system shell kill with negative pid) or to take care of the external app potential children (or simply imagine you fired a shell...); if the external app has acted "daemonic" then one should have knowledge about the app's behaviour, /proc or a process table walker could be of help.

        cheers, --stephan

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://633816]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (3)
As of 2017-01-20 10:54 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (174 votes). Check out past polls.