# # Copyright (c) 2004-2007 - Consultas, PKG.fr # # This file is part of A2P. # # A2P is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # A2P is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with A2P; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # $Id: Signal.pm 3 2007-10-18 16:20:19Z guillaume $ # package A2P::Signal; use strict ; use integer ; use Carp qw(longmess); use sigtrap qw(any normal-signals error-signals old-interface-signals IO URG CLD CHLD); use A2P::Globals ; use A2P::Syslog ; BEGIN { use Exporter (); our ( $VERSION , @ISA , @EXPORT , @EXPORT_OK ); $VERSION = sprintf "%s", q$Rev: 1029 $ =~ /(\d[0-9.]+)\s+/ ; @ISA = qw(Exporter); @EXPORT = qw( $do_init $do_check $do_quit $do_ping $do_test $Childquit @SigDebug @SigInfo @SigWarn @PIPE ); @EXPORT_OK = qw(&LogSigMessage); } our $VERSION ; ############################################################################# ## Signal handling vars ## ############################################################################# our @SigDebug = (); our @SigInfo = (); our @SigWarn = (); # Socket list to be checked when receiving a SIGPIPE our @PIPE ; # Some used flags our $do_init = 1 ; our $do_check = 1 ; our $do_quit = 0 ; our $do_ping = 0 ; our $do_test = 0 ; our $Childquit = 0 ; ############################################################################# ## Signal handling code ## ############################################################################# sub SigABRT { $do_quit += 5 ; push @SigWarn , "SIGABRT: Notified to abort ($do_quit)"; $MUSTQUIT ++ ; exit(1) if ( $do_quit > 9 ); $NO_SYSLOG_DEBUG = 0 if $SERVICE_DEBUG ; } sub SigQUIT { push @SigDebug , "Notified to quit by 'SIG$_[0]' signal"; exit(1) if ( ++ $do_quit > 3 ); } sub SigHUP { push @SigDebug , "SIGHUP received"; $do_init ++ ; my $touch_file = $SERVICE_TMP . '/init_' . $Progname ; if ( -d $SERVICE_TMP and -e $touch_file ) { my $now = time ; utime $now, $now, $touch_file ; } else { push @SigWarn , "Can't touch file '$touch_file' on SIGHUP" ; } } sub SigALRM { $do_check ++ if $DO_PING ; push @SigDebug , "SIGALRM received"; } sub SigDIE { my $info = $_[0] || "" ; my $sub ; chomp $info ; # Forget DIE signal when loading Storable.pm and Log/Agent.pm not present return if ( $info =~ /Log\/Agent.pm/ ); my ($package, $filename, $line) = caller(); # Forget Encoding integration signal... return if ( $filename =~ /Encode.pm/ ); # As a thread should has shutdown, we should check our services ++ $do_check ; push @SigWarn , "Got '__DIE__' signal", &longmess(@_) ; } sub SigPIPE { my ($package, $filename, $line) = caller(); push @SigDebug , "SIG@_ received at L. $line in $filename: $! $?" ; unless ( grep { defined($_) } @PIPE ) { push @SigWarn , "Got '$_[0]' signal" ; $MUSTQUIT ++ ; } } sub SigINT { # Just print info in log about where we were called &Info("debug: SIG" . &longmess(@_)); } sub SigWARN { push @SigWarn , "Got '__WARN__' signal", &longmess(@_) ; } sub SigUSR1 { $do_test ++ ; } my $templogger = 0 ; my $temp_NO_SYSLOG_DEBUG = $NO_SYSLOG_DEBUG ; sub SigUSR2 { push @SigInfo , "Got 'USR2' signal", &longmess(@_) ; $templogger = $loggertid if $loggertid ; $loggertid = $loggertid ? 0 : $templogger ; # Switch advanced debugging mode if ( $ADVANCED_DEBUGGING = $ADVANCED_DEBUGGING ? 0 : 1 ) { $temp_NO_SYSLOG_DEBUG = $NO_SYSLOG_DEBUG ; $NO_SYSLOG_DEBUG = 0 ; } else { $NO_SYSLOG_DEBUG = $temp_NO_SYSLOG_DEBUG ; } &debugdev("ADVANCED_DEBUGGING=$ADVANCED_DEBUGGING NO_SYSLOG_DEBUG=$NO_SYSLOG_DEBUG"); } map { eval q|$SIG{'| . $_ . q|'} = \&Sig| . $_ } qw( PIPE ABRT QUIT HUP ALRM USR1 USR2 ); $SIG{'INT'} = \&SigINT ; $SIG{'SEGV'} = \&SigPIPE ; $SIG{'TERM'} = \&SigQUIT ; $SIG{'__DIE__'} = \&SigDIE ; $SIG{'__WARN__'} = \&SigWARN ; $SIG{'CHLD'} = sub { $Childquit ++ } ; sub _log_list { my $callback = shift ; my $list = shift ; my %mesg = () ; while (@{$list}) { my $message = shift @{$list} ; next unless (defined($message) and $message); $mesg{$message} = 0 unless (exists($mesg{$message})); &$callback($message. (($mesg{$message}++) ?" ($mesg{$message} times)" : "" )); } } sub LogSigMessage { &_log_list( \&Warn, \@SigWarn ); &_log_list( \&Info, \@SigInfo ); &_log_list( \&Debug, \@SigDebug ); } &Debug("Module " . __PACKAGE__ . " v$VERSION loaded"); 1;