Thx Apero. It was very nice explanation. I got what you are trying to say.
one more twist i need to add. What if I fork another process before forking there 3 processes?
example:
#!/usr/local/bin/perl -w
use strict;
use warnings;
use IO::Socket::INET;
use IO::Handle;
use IO::Select;
require POSIX; # provides WNOHANG
# Set up a signal handler.
# This prevents child processes from becoming zombies.
# The subroutine is defined further below.
$SIG{CHLD} = \&reap_kids;
my $IsParent = 1;
my $ListenPort = 5000;
my $PPID = $$;
sub StartServer
{
(my $Port) = @_;
print "StartServer($Port) \n";
my %data;
my %nextpass;
my $bufs ="";
my $tbufs;
my $TempSessionID = "12345";
$0="UE_ServerListen_$TempSessionID\_Port_$Port";
# Rename process
my $socket = new IO::Socket::INET (
LocalHost => '127.0.0.1',
LocalPort => $Port,
Proto => 'tcp',
Listen => $Port,
Blocking => 0,
Reuse => 1
) or die "ERROR in Socket Creation : $!\n";
# Bound to 127.0.0.1:$Port
my $select = IO::Select->new($socket) or die "IO::Select $!";
# server waiting for client connection on port $Port
print "Server started listen on port $Port \n";
my $IsRunning = 1;
while($IsRunning) {
# Fix For UEC process stays alive in the BG
my $exists = kill 0, $PPID;
print "Parent is dead exiting...\n" if (!$exists);
$data{'Sys_Status'} = 0 if (!$exists);
$IsRunning = 0 if (!$exists);
my @ready_clients = $select->can_read(0);
foreach my $fh (@ready_clients) {
if($fh == $socket) {
# New client $fh (total clients: (($select->count)-1)
my $new = $socket->accept();
$select->add($new);
}
}
@ready_clients = $select->can_read(0);
foreach my $fh (@ready_clients) {
if($fh != $socket) {
$fh->recv(my $tmpbufs,1024);
if ($tmpbufs)
{
my $bufs="";
my $tbufs="";
$bufs=$nextpass{$fh} if $nextpass{$fh};
if (substr($tmpbufs, -1) ne "\n") {
for (my $x=length($tmpbufs);$x>=1;$x--) {
if (substr($tmpbufs, $x,1) eq "\n") {
$tbufs=substr($tmpbufs,0, $x);
$nextpass{$fh}=substr($tmpbufs,$x+1);
last ;
}
}
$bufs.=$tbufs;
} else {
my $tmp = $nextpass{$fh};
if ((defined($tmp)) && ($tmp ne '')) {
$bufs= $nextpass{$fh}.$tmpbufs;
$nextpass{$fh}="";
} else {
$bufs= $tmpbufs;
$nextpass{$fh}="";
}
}
chomp($bufs);
foreach my $buf ((split(/\n/,$bufs))) {
chomp($buf);
(my $command,my $key,my $value)=split(/\|/,$buf);
if ($command =~ /Die/) { $IsRunning = 0; exit
+; }
elsif ($command =~ /w/) { $data{$key}=$value;}
elsif ($command =~ /r/) { print $fh "$data{$ke
+y}\n"; }
elsif ($command =~ /m/) { delete $
+data{$key}; }
elsif ($command =~ /e/) { my $ResV
+al = exists($data{$key}); print $fh "$ResVal\n"; }
elsif ($command =~ /s/) { printTS(
+$value . "\n",-1,0.000,$key,1); }
elsif ($command =~ /k/) {
my $count=0;
foreach my $key (keys %data) {
print $fh "$key\n";
}
print $fh "EOT\n";
}
else { print "BAD: $buf \n $bufs|";
}
}
} else {
# Client disconnected
$select->remove($fh);
# Connection Closed: $fh
close($fh);
# Total connected clients => (($select->count)-1)
}
}
}
select(undef,undef,undef, .1);
}
$socket->close();
}
sub ConnectToServer
{
(my $host ,my $Port ,my $cmd_timeout)= @_;
print "ConnectToServer($host ,$Port ,$cmd_timeout) \n";
alarm ($cmd_timeout);
my $t_recv = new IO::Socket::INET (
PeerHost => $host,
PeerPort => $Port,
TimeOut => $cmd_timeout,
Blocking => 1,
Proto => 'tcp',) or print "Unable make connection\n";
alarm 0;
return $t_recv;
}
sub KillServer {
(my $SocketHndl) = @_;
print "KillServer($SocketHndl)\n";
if ((defined($SocketHndl)) && ($SocketHndl != 0)) {
print $SocketHndl "Die\n";
}
}
sub WriteValueToDB
{
(my $Value, my $DbHndl, my $HashKey) = @_;
print "WriteValueToDB($Value, $DbHndl, $HashKey) \n";
if ((defined($DbHndl)) && ($DbHndl != 0)) {
print "Value is $HashKey: $Value, To DB $DbHndl \n";
print $DbHndl "w|$HashKey|$Value\n";
}
}
sub ReadValue {
(my $Key ,my $SocketHndl) = @_;
print "ReadValue($Key ,$SocketHndl) \n";
if ((!defined($SocketHndl)) || ($SocketHndl == 0)) { print "SOCKET H
+ANDLE IS EMTPRT \n"; return undef; }
if (!DoesExists($Key ,$SocketHndl)) { print "CAN NOT FIND THE REC \n
+"; return undef; }
$SocketHndl->send("r|$Key\n");
my $data=<$SocketHndl>;
chomp($data);
return $data;
}
sub DoesExists {
(my $Key, my $SocketHndl) = @_;
print "DoesExists($Key ,$SocketHndl) \n";
my $data;
if ((defined($SocketHndl)) && ($SocketHndl != 0)) {
$SocketHndl->send("e|$Key\n");
$data=<$SocketHndl>;
chomp($data);
}
return $data;
}
#start the IPC server
#----------------------------- MAIN ----------------------------
my $IsPortBusy = 0;
my $socket;
do {
$IsPortBusy = 0;
$ListenPort++;
$socket = new IO::Socket::INET(
LocalHost => '127.0.0.1',
LocalPort => $ListenPort,
Proto => 'tcp',
Listen => $ListenPort,
Blocking => 0,
Reuse => 1) or $IsPortBusy = 1;
} while ($IsPortBusy);
$socket->close();
undef($socket);
my $ServerListenPid = fork();
if (!$ServerListenPid) {
$IsParent = 0;
StartServer($ListenPort);
}
sleep 1;
# Track spawned child processes.
# This is a hash, keyed by the PID.
# We'll use this later to mark them as finished.
my %kids;
for my $child_id (1..3) {
my $pid = fork();
# PARENT: track kid
if ($pid) {
$kids{$pid} = 1;
}
# CHILD: dispatch to child-routine below.
# Explicitly exit, in case the child code neglects.
else {
dispatch_child( $$ );
exit(0);
}
}
print "Main code now waiting for all children.\n";
# Wait for all children to finish.
# The signal handler, reap_kids(), catches finished children.
# Just continue to sleep if there are pending processes.
while( scalar(keys %kids) > 0 ) {
sleep 1;
}
# That's all the main code does.
print "All done with main code.\n";
exit(0);
# ---
# Suborutines
# ---
# Child reaper.
# This will be called when the kernel tells us a process has
# finished running. It's possible more than 1 has done so.
# We run this in a loop to reap all children.
sub reap_kids {
local $!; # good practice. avoids changing errno.
while (1) {
my $kid = waitpid( -1, POSIX->WNOHANG );
last unless ($kid > 0); # No more to reap.
delete $kids{$kid}; # untrack kid.
}
}
# Child dispatch code.
# Here is where you write what your child does.
# Ideally it should exit, but we enforce this above anyway.
sub dispatch_child {
my ($id) = @_; # passed from caller.
print "Hello from child number $id\n";
# Sleep for a random number of seconds.
# Between 5 and 10.
my $seconds = 5 + int(rand(6));
sleep $seconds;
print "Goodbye from child number $id\n";
# Be nice and explicitly exit:
exit(0);
}
Now what is happening is I am getting something like below. I am not sure now how to stop this. One all 3 kids are done I don't want them to execute again. Any suggestions on this too?
StartServer(5001)
Server started listen on port 5001
Hello from child number 1814
Hello from child number 1815
Main code now waiting for all children.
Hello from child number 1816
Goodbye from child number 1814
Goodbye from child number 1816
Goodbye from child number 1815
All done with main code.
$:~/Temp$ Parent is dead exiting...
Hello from child number 2133
Hello from child number 2134
Main code now waiting for all children.
Hello from child number 2135
Goodbye from child number 2134
Goodbye from child number 2133
Goodbye from child number 2135
All done with main code.