tags:

views:

242

answers:

2

I have application that works using Perl's CGI::Fast.

Basically mainloop of the code is:

while (my $cgi = CGI::Fast->new() ) {
  do_whatever( $cgi );
}

Now, I wanted to add ability to kill it, but without disrupting currently processed request. To do so, I added handling to SIGHUP. More or less along the lines:

my $sighupped = 0;
$SIG{ 'HUP' } = sub { $sighupped = 1; };
while (my $cgi = CGI::Fast->new() ) {
  do_whatever( $cgi );
  exit if $sighupped;
}

Which works really great when it comes to "not disturbing process while it handles user request". But, if the process is waiting for new reuqest the sighup-based exit will not be executed until it will finally get some request and process it.

It there any workaround for this? What I would like to achieve it to make the script exit immediately if the HUP (or other signal, it can be changed) reaches it while waiting for request.

+1  A: 

You could redeclare your SIGnals based on where the handler is.

If your outside fast-cgi while loop or inside the fast-cgi polling and thus not in the event loop terminate (basically the default). If your inside the eventloop logic wait for logic to end and terminate.

partdon my lack of a editor at the moment.

$inlogic=0; $hupreq=0; SIG{SIGHUP}={ exit unless($inlogic); $hupreq=1;}

while() { $inlogic=1; function(); $inlogic=0; exit if($hupreq); }

hpavc
+1  A: 

You could use the block version of the eval function and the alarm function to add a timeout to Fast::CGI. In the code below I have set a five second timeout. If it times out it will go back to the start of the loop which will check to see if $continue has been set to zero yet. If it hasn't then it we start a new CGI::Fast object. This means that a maximum of five seconds will go by after you send a HUP before the code will start to stop if it was waiting for a new CGI::Fast object (the timeout has no affect on the rest of the loop).

my $continue = 1;
$SIG{HUP} = sub { $continue = 0 };
while ($continue) {
    my $cgi;
    eval {
        local $SIG{ALRM} = sub { die "timeout\n" };
        alarm 5; #set an alarm for five seconds
        $cgi = CGI::Fast->new;
        alarm 0; #turn alarm off
    };
    if ($@) {
        next if $@ eq "timeout\n"; #we will see the HUP signal's change now
        #died for a reason other than a timeout, so raise the error
        die $@;
    }
    last unless defined $cgi; #CGI::Fast has asked us to exit
    do_stuff($cgi);
}

#clean up
Chas. Owens