LPM: Neat alarm trick

Frank Price fprice at upended.org
Wed Oct 4 13:06:50 CDT 2000


Hi Lexpm:

I found a neat trick and a related question.  First the trick: I have
a script which does rcp system calls.  Sometimes the other server is
screwed up and the system call just hangs for a long time.  I wanted a
away to time it out after a certain amount of time.

The solution is to use alarm().  Alarm sends an ALRM signal to any
children, which works since system() forks a child.  You wrap this in
an eval block, and set a ALRM signal handler.  Outside the eval, you
can test for $@ and take action.  

Example:

eval {
    local $SIG{'ALRM'} = sub { 
		local $SIG{'TERM'} = 'IGNORE';
	    kill TERM => -$$;
	    die 'Caught alarm signal'; 
		};
		alarm(10);
		print "starting system call ...\n";
		system("cp /dev/zero /dev/null");
		alarm(0);
};
if ($@) {
   if ($@ =~ /Caught alarm signal/) { 
	   die ("system call blocked!!!");
   } else { die }
}

Here's the question:  since I want to kill the system call if the
alarm goes off, looks like I have to explicitly send it a TERM signal.
That's why the $SIG{'ALRM'} does 'kill TERM => -$$' (this sends a TERM
to everything in the process group).  First I ignore TERM for this
process so the script doesn't get killed off.  But I really just want
to kil the system() child; however I couldn't find a good way to find
it's PID.  Is there a better way?

Thanks,

-Frank.
-- 
Frank Price | fprice at upended.org | www.upended.org/fprice/
GPG key: www.upended.org/fprice/gpg.asc | E Pluribus Unix




More information about the Lexington-pm mailing list