Hardy has asked for the wisdom of the Perl Monks concerning the following question:

Hello Perl Monks,

I have a problem with my client socket server. I have a daemon running in the same script as I have the web server running. the daemon is catching the term (as well as the int, pipe, and hup) signal. when the read process sends a term signal via the kill command to its corresponding write process, I think it is being caught by the daemon code. is there a way to stop this.

also, do you see any problems in the logic of my code? this is my first time doing this and I have already caused serious problems testing my daemon/web server code on my host providers servers. it was looping endlessly and freezing up their system. this is not that code. this is the code with all the email notifications and possible email loops taken out.

the daemon worked great as a stand alone script and the web server worked great as a stand alone script as well. the problems started when I combined the two scripts into one script.

therefore, I wanted to ask the monks about this combined code before trying it in real time again.

#load posix support for trapping signals use POSIX(); #start of creating a cross-platform method of determining the current +script path and name use FindBin(); use File::Basename(); use File::Spec::Functions; my $script = File::Basename::basename($0); my $SELF = catfile $FindBin::Bin, $script; #end of creating a cross-platform method of determining the current sc +ript path and name #create a new signal set my $sigset = POSIX::SigSet->new(); #create the action you want performed on terminate signals my $termAction = POSIX::SigAction->new('sigTERM_handler', $sigset, &POSIX::SA_NODEFER); #attach the signal to the action you want performed on terminate signa +ls POSIX::sigaction(&POSIX::SIGTERM, $termAction); . . . #the above would be done for the int, pipe, and hup signals. #start of the sub to run when the terminate signal arrives sub sigTERM_handler { #store the signal sent by the system my $HTPad_signalCaught = shift; #run the handler for all exit signals &HTPad_exitSignalHandler("Terminate", $HTPad_signalCaught); } #end of the sub to run when the terminate signal arrives #start of the handler for all exit signals sub HTPad_exitSignalHandler { #reinstate the passed variables my $HTPad_exitType = shift; my $HTPad_signalCaught = shift; #this daemon handler would process the int, pipe, and hup signals. unless (exec($SELF, @ARGV)) { Die "Could not restart the script after a $HTPad_signalCaught signal + was received: $!"; } } #end of the handler for all exit signals #ignore child signals in order to do automatic child reaping $SIG{CHLD} = 'IGNORE'; #enter the web server &HTPad_webSserver(); #start of the web server sub HTPad_webSserver { . . . open a socket . . . #start of the parent server accepting clients while ($HTPad_client = $HTPad_server->accept()) { . . . parent fork() a write process for the client . . . process data from the client . . . #close the write child connection close($HTPad_client); #exit the write child to keep it from accepting new clients exit(1); #should this be 1 or something else? parent fork() a read process for the client . . . process data from the client . . . #send sig term to write child when client closes connection kill ("TERM", $clientWritePID); #close the read child connection close($HTPad_client); #exit the read child to keep it from accepting new clients exit(1); #should this be 1 or something else? } #end of the parent server accepting clients } #end of the web server

...waiting for the world to change...

Replies are listed 'Best First'.
Re: getting a posix daemon and a web server to work together
by TOD (Friar) on Aug 08, 2007 at 02:40 UTC
    as far as i understand your code, it tries to restart itself after the occurrence of any of the trapped signals. obviously this will run into an endless loop. apart from this i wonder whether you always know, in which of the several processes you create you're actually being in. you might get a cleaner and thus less error prone code if you switch from fork'ing to threads. because then everything will be part of one process, you'll be able to install common hooks for all signals - and besides you will have a simple means of generating log messages, which will probably help you find all the other things that aren't working as you expect them to do. e.g.:
    #!/usr/bin/perl -w use strict; [...] # use whatever else use threads; use threads::shared; use Thread::Queue; [...] sub logger; our ($logs, $logger); $logs = Thread::Queue->new; $logger = threads->new(\&logger, "/path/to/logfile"); our $DEBUG : shared = 1; # care for signals: $SIG{INT} = $SIG{QUIT} = $SIG{CONT} = $SIG{STOP} = $SIG{TSTP} = $SIG{CHLD} = $SIG{TRAP} = $SIG{USR1} = $SIG{TTIN} = $SIG{TTOU} = $SIG{VTALRM} = $SIG{ALRM} = \&sig_ignore; $SIG{PIPE} = \&sig_pipe; $SIG{BUS} = $SIG{ILL} = $SIG{SEGV} = $SIG{FPE} = 'DEFAULT'; $SIG{HUP} = $SIG{ABRT} = $SIG{TERM} = $SIG{KILL} = \&sig_handler; $SIG{__WARN__} = $SIG{__DIE__} = sub { $logs->enqueue(shift) }; # now install all the other threads you want to run. # everything they have to do in case something goes wrong, # will be to simply warn() or die() - roughly told. # hence the logger finction is quite simple: sub logger { my $logfile = shift; open LOG, ">>$logfile" || die $!; while (my $msg = $logs->dequeue) { my $line = "[".localtime(time)."] $msg"; chomp $line; print LOG "$line\n"; flush LOG if $DEBUG; } close LOG; } [...] sub sig_ignore { return unless @_; $logs->enqueue("Silently ignoring signal ".shift); } sub sig_pipe { return unless @_; my $warn = "Caught signal ".shift().", "; # append more information to the warning message # if necessary $logs->enqueue($warn); } # the sig_handler() function has to carefully wait for all # threads to terminate properly and then simply exit - # which means again that there is only one process # to care for: sub sig_handler { return unless @_; $logs->enqueue(undef); $logger->join; [...] exit 0; }
    these were very short excerpts from a daemon that i once wrote and which has now been running for years. without their context the lines may look rather obfuscating at the first glance, but i think that after a lecture on perldoc perlthrtut you will understand what they're intending.

    hope i could be some sort of helpful
    regards
    --------------------------------
    masses are the opiate for religion.
      I thought about threads in the beginning but my host provider said threads were not being supported on their servers because threads were not safe for most modules or something like that. Is there any way to turn off the daemon commands for the children only? I really need help because I don't want to crash their servers again with my endless loop. why exactly was it ending up in an endless loop? --- skype: hardManHardy ---
      ...waiting for the world to change...
        also, what host provider are you using to run your thread daemon on and how much does it cost? I am trying to write a daemon and a web server for turn based multi player games. this is why I need a web server accepting clients (lots of clients) and why I need a daemon to keep the script running at all times.
        Skype: hardManHardy
        ...waiting for the world to change...