Zombie problem when creating a listening Socket

Discussion in 'Perl Misc' started by vikrant, Sep 14, 2005.

  1. vikrant

    vikrant Guest

    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
     
    vikrant, Sep 14, 2005
    #1
    1. Advertising

  2. vikrant

    Anno Siegel Guest

    vikrant <> wrote in comp.lang.perl.misc:
    > 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]
    > -----------------------------------------------------------------
    >
    > #!/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



    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Sep 14, 2005
    #2
    1. Advertising

  3. vikrant

    vikrant Guest

    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
     
    vikrant, Sep 16, 2005
    #3
  4. vikrant

    Anno Siegel Guest

    vikrant <> wrote in comp.lang.perl.misc:
    > 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


    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);
    > }
    >
    > --------------------------------------------------------------------
    >
    > The OUTPUT of the Program after successful execution is:-


    Successful? Hmmm...

    > -----------------------------------------------------------------------------
    > Can't call method "send" on an undefined value at socketmodule.pl line 41.


    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
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Sep 16, 2005
    #4
  5. vikrant

    vikrant Guest

    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);
    }
    -----------------------------------------------------------------------------------------

    Output is
    -----------------------------------------------------------
    server.pl 3618: begat 3620 at Fri Sep 16 16:23:37 2005
    server.pl 3618: reaped 3620 at Fri Sep 16 16:23:37 2005
    -----------------------------------------------------------

    With Regards

    Vikrant
     
    vikrant, Sep 16, 2005
    #5
  6. vikrant

    Anno Siegel Guest

    vikrant <> wrote in comp.lang.perl.misc:

    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
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Sep 16, 2005
    #6
  7. vikrant

    Guest

    vikrant <> wrote:
    > 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

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Sep 16, 2005
    #7
  8. vikrant

    vikrant Guest

    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
     
    vikrant, Sep 17, 2005
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christian von Essen

    Listening socket not seen outside of localhost

    Christian von Essen, Jun 21, 2004, in forum: Python
    Replies:
    2
    Views:
    438
    Christian von Essen
    Jun 21, 2004
  2. pwilkins
    Replies:
    7
    Views:
    471
    Grant Edwards
    Jun 25, 2005
  3. Giovanni Tumiati
    Replies:
    2
    Views:
    345
    Grant Edwards
    Jun 25, 2005
  4. Jp Calderone
    Replies:
    1
    Views:
    351
    Grant Edwards
    Jun 25, 2005
  5. serge.john.swilting

    plouk zombie plouk zombie

    serge.john.swilting, Aug 19, 2003, in forum: Perl Misc
    Replies:
    1
    Views:
    204
    hudson
    Aug 20, 2003
Loading...

Share This Page