Jim,

Thank you! This was a big help to me in that I ran into this problem from two 
directions recently, with a perl daemon and with Apache::SIG.. I did find some info 
about fixing this for real rather than using unsafe signals. They mostly seemed to 
point to using the POSIX sigaction methods rather Perl's. 

I did end up getting my daemon to work without either dying after the first command or 
spawning endless children that would not die, those were my two choices before :) Only 
a part of this was related to the signal problem, but it was the hard part for a 
while. 

The child signal was what was causing me big problems. I know this is far from a 
complete answer, but I hope it might send someone off on the right path if they don't 
want to set the ENV var. I was worried about doing it that way, because what happens a 
year from now when I upgrade my server and we somehow forget about that little detail? 
 I know me and I will manage to mess it up if I can :) 

Below are some examples from the POSIX module, it should work :). I found most of this 
somewhere when doing research on perl daemons but the child one I added on and I am 
currently using all of the below, I just did some cutting of other things.

use POSIX ();
use POSIX 'WNOHANG';
use FindBin ();
use File::Basename ();
use File::Spec::Functions;

my $script = File::Basename::basename($0);
my $SELF = catfile $FindBin::Bin, $script; 

my $sigset = POSIX::SigSet->new();
  my $action = POSIX::SigAction->new('sigHUP_handler',
                                     $sigset,
                                     &POSIX::SA_NODEFER);
  my $action_alrm = POSIX::SigAction->new('sigALRM_handler',
                                     $sigset,
                                     &POSIX::SA_NODEFER);  
  my $action_child = POSIX::SigAction->new('sigCHLD_handler',
                                     $sigset,
                                     &POSIX::SA_NODEFER);                              
                                        
                                     
  POSIX::sigaction(&POSIX::SIGHUP, $action);
  POSIX::sigaction(&POSIX::SIGALRM, $action_alrm);
  POSIX::sigaction(&POSIX::SIGCHLD, $action_child);
  
  sub sigHUP_handler {
      print "got SIGHUP\n";
      exec($SELF, @ARGV) or die "Couldn't restart: $!\n";
  }
  sub sigALRM_handler {
      print "got ALARM timeout\n";
            
  }
  sub sigCHLD_handler {
      while (my $reaperpid = waitpid(-1,WNOHANG)>0) {
      }
  }


## do your while (1) and  fork etc... 



I wish I could paste in my whole daemon thing, but it is too far along with to many 
things specific to my bosses application.. 

Thanks,

Eric 

At 02:55 PM 6/15/2004, Jim Albert wrote:
>Last week I had a problem where I could not get my Apache2/mod_perl2/perl5.8.3 web 
>server to catch a SIGPIPE signal in a timely manner.  I was asked to post a 
>description of this problem and solution to this list so that it might be included in 
>future mod_perl documentation.
>
>Feel free to adjust this description as necessary when integrating it into the 
>appropriate documentation.
>
>The Problem:
>Use a PerlFixupHandler to catch when the pipe from browser to httpd server has been 
>broken such as when the user presses the browser stop button.
>
>In conf.d/perl.conf
>PerlFixupHandler Apache::SIG2
>
>where Apache::SIG2.pm is defined in this example as:
>
>----------
>package Apache::SIG2;
>
># This package adapted by Jim Albert from the original mod_perl1
># Apache::SIG.pm by Doug MacEachern and Doug Bagley
># This PerlHandler can be used to prevent httpd children from killing
># off non-mod-perled CGIs when the user presses the Stop button.
>
>use strict;
>use Apache::RequestRec;
>use ModPerl::Util;
>use Apache::Const;
>
>sub handler {
>    my $r = shift;
>    if (!$r->main) {
>        $SIG{PIPE} = \&PIPE;
>    }
>
>   return OK;
>}
>
>sub PIPE {
>   my($signal) = @_;
>   print STDERR ("User pressed stop button.\n");
>   # Kill off the httpd child before it can kill any running CGIs.
>   # Or do whatever other cleanup is appropriate.
>   CORE::exit();
>}
>
>1;
>----------
>
>With the introduction of perl 5.8.0, this handler no longer works as expected because 
>of the introduction of perl safe signals.
>See:
>http://www.perldoc.com/perl5.8.4/pod/perlipc.html#Deferred-Signals-(Safe-Signals)
>
>What happens with perl 5.8 and safe signals is that the apache httpd child does 
>receive the SIGPIPE, but it is delayed and the perl CGI program has already been 
>killed.  The httpd child does not act on the SIGPIPE until it receives the next httpd 
>request.
>
>The Solution:
>An Apache server_startup.pl script can be used to turn off perl safe signals with the 
>following line:
>$ENV{PERL_SIGNALS} = "unsafe";
>The server_startup.pl script can be included via the following line in perl.conf:
>PerlRequire conf/server_startup.pl
>The ability to revert back to "unsafe" signals is available as of perl 5.8.1.
>
>-- 
>Jim Albert
>
>
>
>-- 
>Report problems: http://perl.apache.org/bugs/
>Mail list info: http://perl.apache.org/maillist/modperl.html
>List etiquette: http://perl.apache.org/maillist/email-etiquette.html


-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html

Reply via email to