Zombie problem when creating a listening Socket

V

vikrant

Hi

I have written a code for Listening socket(Server) that serve multiple
clients request.The Socket(Server) accept the data from clients and send
back them the same data for validation.

But,I am facing a problem while running the following code .The code
creating a Zombie for each client request.
-----------------------------------------------------------------

#!/usr/bin/perl
use IO::Select;
use IO::Socket::INET;

#LISTENING SOCKET
$sListening_Socket = new IO::Socket::INET (LocalPort => 36545,
Proto => "tcp",
Listen => 4,
Type => SOCK_STREAM)
or die "Could not create socket";

REQUEST:
while ($sNew_Socket = $sListening_Socket->accept())
{
if($iChild_Pid=fork) #Check the Child Process ID
{
close ($sNew_Socket); #Parent closes unused handle
next REQUEST;
} defined($iChild_Pid) or die "Cannot fork";

close ($sListening_Socket); #Child closes unused Handle

$obSelected_Socket = IO::Select->new($sNew_Socket);
while( $obSelected_Socket->can_read(20)) #Wait for 20 seconds
{
sysread($sNew_Socket,$sBuffer,1<<10);
$sData_Recevied.=$sBuffer;
if($sBuffer =~/\/message_end>/)
{
last;
}
}

$sNew_Socket->send($sData_Recevied);
close($sNew_Socket);
exit;
}
------------------------------------------------------------------------------------
Also,when i run the following command

ps -A|grep perl

3466 pts/1 00:00:00 perl
3469 pts/1 00:00:00 perl <defunct>
3473 pts/1 00:00:00 perl <defunct>
3478 pts/1 00:00:00 perl <defunct>
3482 pts/1 00:00:00 perl <defunct>
3486 pts/1 00:00:00 perl <defunct>
3490 pts/1 00:00:00 perl <defunct>

please known me if i am missing something.

With Regards

Vikrant
 
A

Anno Siegel

vikrant said:
Hi

I have written a code for Listening socket(Server) that serve multiple
clients request.The Socket(Server) accept the data from clients and send
back them the same data for validation.

But,I am facing a problem while running the following code .The code
creating a Zombie for each client request.

Your code doesn't care about its kids, sure they end up becoming zombies.

Try setting $SIG{ CHLD} = 'IGNORE' in the parent. If that doesn't help,
install a reaper. Look for "zombie" and "REAPER" in perlipc for more.

Anno


[original code]
 
V

vikrant

hi

Now, I have made some changes in the code but still facing the problem.This time the socket no more
listening to client resquests.

Changed Code is
------------------------------------------------------------------------------------------------

#!/usr/bin/perl
use IO::Select;
use IO::Socket::INET;

$sListening_Socket = new IO::Socket::INET (LocalPort => 36545,
Proto => "tcp",
Listen => 4,
Type => SOCK_STREAM
) or die "Could not create socket";

sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
use POSIX ":sys_wait_h";
sub REAPER
{
my $child;
while (($pid = waitpid(-1,WNOHANG)) > 0)
{
logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
}
$SIG{CHLD} = \&REAPER; # loathe sysV
}

$SIG{CHLD} = \&REAPER;
$pid=0;
while ($sNew_Socket = $sListening_Socket->accept()|| $pid)
{
next if $pid = fork;
die "fork: $!" unless defined $pid;

$obSelected_Socket = IO::Select->new($sNew_Socket);

while( $obSelected_Socket->can_read(20))
{
sysread($sNew_Socket,$sBuffer,1<<10);
$sData_Recevied.=$sBuffer;
if($sBuffer =~/\/message_end>/)
{
last;
}
}
$sNew_Socket->send($sData_Recevied);

close($sListening_Socket);
$pid=0;
exit;
} continue {
close($sNew_Socket);
}

--------------------------------------------------------------------

The OUTPUT of the Program after successful execution is:-
-----------------------------------------------------------------------------
Can't call method "send" on an undefined value at socketmodule.pl line 41.
socketmodule.pl 4031: reaped with exit 65280 at Fri Sep 16 11:51:17 2005
---------------------------------------------------------------------------------

Please correct me if i have made any mistake actually i am new to perl.

With Regards
Vikrant
 
A

Anno Siegel

vikrant said:
hi

Now, I have made some changes in the code but still facing the
problem.This time the socket no more
listening to client resquests.

Changed Code is

You're not using strict and warnings. Do that and declare all variables
lexically.
use IO::Select;
use IO::Socket::INET;

$sListening_Socket = new IO::Socket::INET (LocalPort => 36545,
Proto => "tcp",
Listen => 4,
Type => SOCK_STREAM
) or die "Could not create socket";

sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
use POSIX ":sys_wait_h";
sub REAPER
{
my $child;
while (($pid = waitpid(-1,WNOHANG)) > 0)
^^^^
You are saving the pid to $pid.
{
logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');

Here you are trying to print the value of $waitedpid. Which is it?
}
$SIG{CHLD} = \&REAPER; # loathe sysV
}

$SIG{CHLD} = \&REAPER;
$pid=0;
while ($sNew_Socket = $sListening_Socket->accept()|| $pid)
^^^^^^^
What do you thin to achieve with "... || $pid"? $sNew_Socket is supposed
to be a Socket object. $pid is an integer (as far as I can see).
{
next if $pid = fork;

After a fork() you almost always have to branch on the value of $pid,
otherwise the same code will be run in the parent and the kid. This
seems to be what's happening here.
die "fork: $!" unless defined $pid;

$obSelected_Socket = IO::Select->new($sNew_Socket);

while( $obSelected_Socket->can_read(20))
{
sysread($sNew_Socket,$sBuffer,1<<10);
$sData_Recevied.=$sBuffer;
if($sBuffer =~/\/message_end>/)
{
last;
}
}
$sNew_Socket->send($sData_Recevied);

close($sListening_Socket);
$pid=0;
exit;
} continue {
close($sNew_Socket);
}

Successful? Hmmm...

So $sNew_Socket is undefined when the line is called. At a glance it's
hard to see how that can happen in light of the (otherwise suspect)
" ... || $pid" in the assignment. However, you are using the same
global variable $pid in the REAPER routine. That's probably where it
is set to undef.

So make the program strict- and warnings-proof and declare your variables
lexically. Then try again.
socketmodule.pl 4031: reaped with exit 65280 at Fri Sep 16 11:51:17 2005
^^
Notice the two blanks where a pid should appear? That's because of
the the $pid/$waitedpid mixup in the REAPER routine.

Anno
 
V

vikrant

Thanks for correcting me.But one problem is still there.The Socket no more listening to next request
that means forking could not happened.

Suggest me the changes needs to do.So,that the code work properly.

The Code is:-
-----------------------------------------------------------------------------------------
#!/usr/bin/perl -w

use strict;
use IO::Select;
use IO::Socket::INET;

my($pid,$sBuffer,$sData_Recevied,$iZombie);

my $sListening_Socket = new IO::Socket::INET (LocalPort => 36545,
Proto => "tcp",
Listen => 4,
Type => SOCK_STREAM
) or die "Could not create socket";

sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
use POSIX ":sys_wait_h";
sub REAPER
{

while (($iZombie = waitpid(-1,WNOHANG)) > 0)
{
logmsg "reaped $iZombie" . ($? ? " with exit $?" : '');
}
$SIG{CHLD} = \&REAPER; # loathe sysV
}

$SIG{CHLD} = \&REAPER;


while (my $sNew_Socket = $sListening_Socket->accept())
{
if (!defined($pid = fork()))
{
logmsg "cannot fork: $!";
}
elsif ($pid)
{
logmsg "begat $pid";
next;
}
my $obSelected_Socket = IO::Select->new($sNew_Socket);

while( $obSelected_Socket->can_read(20))
{
sysread($sNew_Socket,$sBuffer,1<<10);
$sData_Recevied.=$sBuffer;
if($sBuffer =~/\/message_end>/)
{
last;
}
}

$sNew_Socket->send($sData_Recevied);
close($sListening_Socket);
exit;
} continue {
close($sNew_Socket);
}
 
A

Anno Siegel

Please show an attribution and some context with your reply.
Thanks for correcting me.But one problem is still there.The Socket no
more listening to next request
that means forking could not happened.

Suggest me the changes needs to do.So,that the code work properly.

I realize English is not your first language, but that sounds pretty
rude. I'm not your servant.

I can't spend the time needed to completely debug this still rather
messy program, but it seems that after the first fork the kid process
is running the main loop instead of the parent. If you comment out
the lines

# close($sListening_Socket);
# exit;

in your code you will be able to connect multiple times to your
server, but look at the log messages:

./ttt 30280: begat 30282 at Fri Sep 16 13:49:32 2005
./ttt 30282: begat 30284 at Fri Sep 16 13:50:08 2005
./ttt 30280: begat 30286 at Fri Sep 16 13:50:20 2005

Notice how the PID of the "parent"-process changes. That is not how
a server normally runs. The parent is supposed to accept() all
connections and fork off a kid to handle the actual transaction, so
the first PID should be the same in all instances.
The Code is:-
-----------------------------------------------------------------------------------------
#!/usr/bin/perl -w

use strict;
use IO::Select;
use IO::Socket::INET;

my($pid,$sBuffer,$sData_Recevied,$iZombie);

This is better, but you're only halfway there.

Lexical variables should be declared as close to their first use as
possible, not all in one place. You noticed how the double use of
the variable $pid in REAPER and the main program messed up your earlier
version. The same can still happen when you declare the lexical $pid
once for the rest of the program. Declare it where it is used, not
before. The same goes for the other variables.
my $sListening_Socket = new IO::Socket::INET (LocalPort => 36545,
Proto => "tcp",
Listen => 4,
Type => SOCK_STREAM
) or die "Could not create socket";

sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
use POSIX ":sys_wait_h";
sub REAPER
{

while (($iZombie = waitpid(-1,WNOHANG)) > 0)
{
logmsg "reaped $iZombie" . ($? ? " with exit $?" : '');
}
$SIG{CHLD} = \&REAPER; # loathe sysV
}

$SIG{CHLD} = \&REAPER;


while (my $sNew_Socket = $sListening_Socket->accept())
{
if (!defined($pid = fork()))
{
logmsg "cannot fork: $!";
}
elsif ($pid)
{
logmsg "begat $pid";
next;
}
my $obSelected_Socket = IO::Select->new($sNew_Socket);

while( $obSelected_Socket->can_read(20))
{
sysread($sNew_Socket,$sBuffer,1<<10);
$sData_Recevied.=$sBuffer;
if($sBuffer =~/\/message_end>/)
{
last;
}
}

$sNew_Socket->send($sData_Recevied);
close($sListening_Socket);
exit;

Comment out the above two lines and watch what's happening.
} continue {
close($sNew_Socket);
}

Anno
 
X

xhoster

vikrant said:
hi

Now, I have made some changes in the code but still facing the
problem.This time the socket no more listening to client resquests.


You had code that was (apparently) working fine, other than that it left
zombies. Why did you competely re-write that code into this mess?

Most likely, all you had to do was add $SIG{ CHLD} = 'IGNORE'; near the top
of your code, and leave the rest of the code unchanged.

<snip tangled mess>

Xho
 
V

vikrant

hi Anno
I realize English is not your first language, but that sounds pretty
rude. I'm not your servant.

i did not did it intentionally but pardon me if i sounded a bit rude to u.

Thanks for the information and time u give to me.

With Regards

Vikrant
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top