piyush has asked for the wisdom of the Perl Monks concerning the following question:
#!/opt/perl-5.6.1/bin/perl ###################################################################### +########## ############ #Initial Phase: Make a working daemon. #Second Phase: Fork child processes. #Third phase: Build a basic framework wherein the individual pieces of + functionalities can be just plugged in. #Fourth Phase: Build the individual pieces of checks / other functiona +lities like debug option, logging other checks etc. #Fifth Phase: Bind the different functionalities with the basic framew +ork. #Sixth Phase: Test the compelete script. #Seventh Phase: Performance improvement. ###################################################################### +########## ############ use POSIX; use FileHandle; use File::Basename; use IO::Handle; #$PGM=basename($0); $DEF_TIMEOUT=60; $CHILD_TIMEOUT=10; $NUM_OF_KIDS=4; $shutitdown=0; #Please do not change this value. my $pid; my $file='/home/hkitmond/test.txt'; my $file2='/home/hkitmond/pid.txt'; my $logfile='/home/hkitmond/log'; STDOUT->autoflush(1); STDERR->autoflush(1); @jobs = (); %job = (); ###############Install signal handler############ $SIG{'TERM'}=$SIG{'INT'}=$SIG{'HUP'}=$SIG{'QUIT'}='shutdown'; ################################################# if ($pid=fork()){ print "\nI am the parent and just forked a child that has this PID:$pi +d"; #####Log this PID somewhere so that it can be used while issuing /bin/ +kill -s TERM <PID>############## open(PIDFILE, '>/home/hkitmond/pid.txt'); print PIDFILE "$pid"; close(PIDFILE); ###################################################################### +################################ print "\nExiting.."; exit 0; } elsif(!defined $pid){ print "\nCouldn't fork child. Probably process table is filled. Get in + touch with sysadm!!"; } else{ #This is the thread that is actually the daemon and it will keep runni +ng forever. setpgrp(0, 0); chdir('/'); print STDOUT "\nI am the child $$ and have just been forked by my pare +nt. Now I have become a daemon."; open(LOGFILE,'>/home/hkitmond/log'); LOGFILE->autoflush(1); while(1){ open(INPUT, $file)||die ("\nCannot open $file"); chomp (@args=<INPUT>); close(INPUT); $i=1; #if ($shutitdown==0){ #foreach $node (@args){ while ($node = shift(@args)){ if ($shutitdown==0){ $READER = "READER$i"; $WRITER = "WRITER$i"; pipe($READER, $WRITER); $WRITER->autoflush(1); if ($pid = fork()){ close($WRITER); $job{$pid}{'pipe'}= $READER; } elsif(!defined $pid){ print "\nCouldn't fork child"; } else{ ###This is the thread invoked per server - it will contain calls to wr +apper scripts for every check. Agent scripts reside on agent. ###This thread will exit after it runs checks and other tasks. ###################################### #Include timeout functionality here to make sure a thread doesn't ling +er too long. #Install the appropriate signal handler for timeout $SIG{'ALRM'}='thread_hung'; alarm $CHILD_TIMEOUT; print STDOUT "\nI am the child $$ corresponding to $node"; setpgrp(0, 0); close($READER); chdir('/'); ################################## #Write code here to call scripts to invoke various checks# #Use timeout functionality #while(1){ #} @RES = system("/usr/sbin/ping $node 3 > /dev/null"); ################################## $m="$$:$node:x_START_x"; print $WRITER "$m\n"; foreach $m (@RES){ print $WRITER "$m\n"; } close($WRITER); ###Exit this thread### exit 0; } ###################################################################### +########### #Need to implement logic to allow no more than defined number of threa +ds to run parallely #while(scalar(keys %job) >= $NUM_OF_KIDS || (%job && (scalar @args < $ +NUM_OF_KIDS))){ while(scalar(keys %job) >= $NUM_OF_KIDS || ((scalar(keys %job) >= 1) & +& (scalar @args == 0))){ print STDOUT "\n".scalar(keys %job).",".scalar @args; print STDOUT "\nWaiting for some child..."; $kpid= wait; #waiting for any child process to finish. This is essenti +al for proper termination of child. print STDOUT "\nJust waited for $kpid child"; #$a = @args; #not sure why this is added. next unless $job{$kpid}; #Not required actually. @kid_stdout = (); $PIPE=$job{$kpid}{'pipe'}; chomp(@kid_stdout=<$PIPE>); close($PIPE); foreach $l (@kid_stdout){ print STDOUT "\n$l"; print LOGFILE "\n$l"; } delete($job{$kpid}); #removing the element from job corresponding to +this process } ##Logic to restrict number of parallel threads less than the predefine +d value ends ###################################################################### +############## print STDOUT "\nGoing to next run of loop"; $i++; } #If block corresponding to $shutitdown=0 ends ###################################################################### +## #Need to include logic such that if a daemon needs to be killed, it ca +tches this signal, does the required cleanup and then exits. #If its req. to stop the daemon, use /bin/kill -9 <PID> command which +will be caught by signal handler and the required cleanup will be don +e. ###################################################################### +## else{ ############################################################## #This block contains logic such that on reception of SIGTERM, the alre +ady forked processes are waited upon by the parent. #We need to consider the situation where some child has already been k +illed as a result of timeout. ############################################################## print STDOUT "\nInside the cleanup section..."; print STDOUT "\nNumber of outstanding processes:".scalar(keys %job)." +.."; while(scalar(keys %job) != 0){ $pid=wait; delete($job{$pid}); print STDOUT "\nJust received exit status of $pid. Waiting for ".scala +r(keys %job)." others before stopping the daemon.."; } print "\nDaemon exiting..."; close(LOGFILE); exit 0; } #Else block corresponding to cleanup i.e. $shutitdown=1 ends } #for loop corresponding to every node from i/p file ends. =piyush ###################################################################### +## #Need to include logic such that if a daemon needs to be killed, it ca +tches this signal, does the required cleanup and then exits. #If its req. to stop the daemon, use /bin/kill -9 <PID> command which +will be caught by signal handler and the required cleanup will be don +e. ###################################################################### +## else{ ############################################################## #This block contains logic such that on reception of SIGTERM, the alre +ady forked processes are waited upon by the parent. #We need to consider the situation where some child has already been k +illed as a result of timeout. ############################################################## print STDOUT "\nInside the cleanup section..."; print STDOUT "\nNumber of outstanding processes:".scalar(keys %job)." +.."; while(scalar(keys %job) != 0){ $pid=wait; delete($job{$pid}); print STDOUT "\nJust received exit status of $pid. Waiting for ".scala +r(keys %job)." others before stopping the daemon.."; } print "\nDaemon exiting..."; exit 0; } #Else block corresponding to cleanup i.e. $shutitdown=1 ends =cut } #End of infinite while loop } #end of daemon code. ##############Subroutines Section##################################### +######## sub shutdown{ print STDOUT "\nReceived stop signal. Stopping the daemon..."; $shutitdown=1; } sub thread_hung{ print STDOUT "\nThread $$ is hung. Aborting.."; $id=$$; $pipe=$job{$id}{'pipe'}; delete($job{$id}); kill -9, $id; close($pipe); }
I am the parent and just forked a child that has this PID:2040 I am the child 2040 and have just been forked by my parent. Now I have + become a daemon. Exiting..hkgisdev02% Going to next run of loop I am the child 2041 corresponding to abcd.pi.com I am the child 2042 corresponding to lonovoprod5.lehman.com Going to next run of loop I am the child 2046 corresponding to lonovoprod6.lehman.com/usr/sbin/p +ing: unknown host abcd.pi.com Going to next run of loop I am the child 2050 corresponding to lonlxvmopsw01.lehman.com 4,587 Waiting for some child... Just waited for 2041 child 2041:abcd.pi.com:x_START_x 256 Going to next run of loop I am the child 2052 corresponding to faicmc01-usrs07.lehman.com 4,586 Waiting for some child... Just waited for 2042 child 2042:lonovoprod5.lehman.com:x_START_x 0 Going to next run of loop 4,585 Waiting for some child... Just waited for 2046 child 2046:lonovoprod6.lehman.com:x_START_x 0 Going to next run of loop I am the child 2056 corresponding to lonintrelay2.lehman.com I am the child 2057 corresponding to losin11pudb4-m.lehman.com 4,584 Waiting for some child... Just waited for 2050 child 2050:lonlxvmopsw01.lehman.com:x_START_x 0 Going to next run of loop 4,583 Waiting for some child... I am the child 2062 corresponding to lonfwmgmt2.lehman.com Just waited for 2052 child 2052:faicmc01-usrs07.lehman.com:x_START_x 0
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Is there any flaw with the way the below daemon forks child processes?
by Bloodnok (Vicar) on Sep 23, 2009 at 09:04 UTC | |
|
Re: Is there any flaw with the way the below daemon forks child processes?
by piyush (Novice) on Sep 23, 2009 at 05:41 UTC |