Almut, thank you for your reply. Here is some test code, I am sorry it is not a 10-liner, but I wanted to maintain the concept of a global object that I have in my application. :)
#!/usr/bin/perl
use strict;
use Getopt::Std;
use Mgr;
use Global1;
my %OPT;
my $ok = getopts("D", \%OPT);
my $BASE = ".";
daemonize();
start();
sub start {
eval {
$SIG{HUP} = \&catchHup;
$SIG{CHLD} = "IGNORE";
$SIG{INT} = \&catchInt;
$SIG{USR1} = \&catchUsr1;
if ($MANAGER) { undef $MANAGER; }
$MANAGER = new Mgr;
$MANAGER->monitor();
};
if ($@) {
Global1::error ("Got fatal error:\n$@\n");
catchInt();
}
}
sub daemonize {
require POSIX;
open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
open STDERR, '>/dev/null' or die "Can't write to /dev/null: $!";
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;
POSIX::setsid() or Global1::error ( "Could not setsid\n$!\n" );
`echo $$ > tun_mgr.pid`;
}
sub catchHup {
Global1::error ( "\n\t!!!Got HUP!!!\n" );
$MANAGER->killAll();
Global1::error ( "\n\tRestarting application\n" );
&start();
}
sub catchInt {
$MANAGER->killAll();
`rm -rf tun_mgr.pid`;
Global1::error ( "Parent process $$ exiting\n" );
exit;
}
package Mgr;
use strict;
use Global1;
sub new {
my $this = {};
$this->{children} = {};
bless $this;
return $this;
}
sub killAll {
my $this = shift;
$SIG{CHLD} = "IGNORE";
foreach (keys %{$this->{children}}) {
my $cpid = $this->{children}->{$_}->{pid};
if (kill INT => $cpid) {
Global1::error ("Killed child $cpid\n");
}
delete $this->{children}->{$_};
}
}
my $usr1 = 0;
my $usr2 = 0;
sub monitor {
my $this = shift;
my $num = 0;
my $pid;
my $ppid = $$;
while ($num < 2) {
unless ($pid = fork()) {
# Child
$SIG{USR1} = \&doPing;
$SIG{INT} = \&gotINT;
$SIG{HUP} = 'IGNORE';
$SIG{USR2} = 'IGNORE';
CHILD_START:
while (! $usr1) {
Global1::error ( "Child $$ sleeping for 10 seconds\n"
+);
sleep(10);
}
$usr1 = 0;
eval {
`echo 1 > $$`;
my $numkill = kill 'USR2' => $ppid;
Global1::error ( "\t$$ Sent SigUSR2 to parent proc
+ess \n" );
goto CHILD_START;
};
sub doPing {
$usr1 = 1;
}
sub gotINT {
Global1::error ( "$$ got INT signal - exiting\n" );
exit;
}
}
# Parent Code
$this->{children}->{$num}->{pid} = $pid;
Global1::error ( "Spawned pinger process $pid child ID # $num\
+n" );
$num++;
}
foreach my $ch (keys %{$this->{children}}) {
my $numkill = kill 'USR1' => $this->{children}->{$ch}->{pi
+d};
Global1::error ( "Parent $$ sent SigUSR1 to process ".$thi
+s->{children}->{$ch}->{pid}." \n" );
}
$SIG{USR2} = \&catchUsr2;
$SIG{HUP} = \&main::catchHup;
$SIG{CHLD} = "IGNORE";
$SIG{INT} = \&main::catchInt;
if ($DEBUG) {
my $msg = "";
foreach (keys %SIG) {
$msg .= "$_ => $SIG{$_}\n";
}
Global1::error ( "Parent's SIG hash:\n$msg\n" );
}
HANGOUT:
while (! $usr2) {
sleep 1;
}
$usr2 = 0;
my $done = 0;
$num = 0;
foreach $num (keys %{$this->{children}}) {
my $fc = $this->{children}->{$num}->{pid};
if (-e $fc) {
Global1::error ( "Parent process $$ recieved USR2 sign
+al from child $fc\n" );
unlink $fc;
kill "USR1" => $fc;
last;
}
}
goto HANGOUT;
sub catchUsr2 {
$usr2 = 1;
}
}
1;
package Global1;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw ( $MANAGER $DEBUG );
$MANAGER = "";
$DEBUG = 1;
sub error {
my $mes = shift;
my $date = scalar (localtime (time));
open (LOG, ">>logfile") or die "Could not open logfile for write:\
+n$!\n";
print LOG "$date\t $mes\n";
close LOG;
}
1;
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.