Possible bug in 5.8.6: accept/fork/wait/exit ?



Any multi-process/networking gurus here?

I'm trying to write a simple forking HTTP proxy but am having a problem when running it with Perl 5.8.6. The program spontaneously exits after one or a few connections. The problem does not happen when I use Perl 5.6.1. I'm running this on Linux with the 2.6.11.4-20a-default kernel (SuSE 9.3).

Here's a short program that demonstrates it, between the bars below. To see the problem: First, run this program from one shell prompt. Then, from another shell prompt, run "telnet localhost 8001". The connection is made then closed, as expected. You can see the output in the first shell window. Now, repeat the telnet command over and over. After 1-20 telnets, the script exits with no message.

----------------------------------------------------------------
#!/usr/bin/perl -w

use strict ;
use Socket ;

use vars qw($LISTEN_PORT  $paddr  $pid  $conn_id) ;

$LISTEN_PORT= shift || 8001 ;

# clean up zombies
$SIG{CHLD}= sub { wait } ;

print "Starting $0, listening on port $LISTEN_PORT.\n" ;

# Set up the listening socket
socket(S_LISTEN, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die ;
setsockopt(S_LISTEN, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or die ;
bind(S_LISTEN, sockaddr_in($LISTEN_PORT, INADDR_ANY)) or die $! ;
listen(S_LISTEN,SOMAXCONN) or die ;

# Accept one connection at a time, and fork a new process to handle it.
for ( ; $paddr= accept(S_CLIENT, S_LISTEN) ; close S_CLIENT) {
    $conn_id++ ;
    select((select(S_CLIENT), $|=1)[0]) ;      # unbuffer the socket
    if ($pid= fork) {    # parent process
        print "starting parent, conn=$conn_id, pid=$$\n" ;
        next ;
    } else {             # child process
        print "starting child,  conn=$conn_id, pid=$$\n" ;
        exit ;
    }
}

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

The problem goes away if I comment out either the exit statement, or the $SIG{CHLD} statement. Of course, neither one is acceptable, because all the extra processes would keep hanging around (either as processes or zombies). If the for() loop is replaced with a simple "while (1)" loop, the problem goes away, so the accept() seems to be part of the problem.

Does anyone have any ideas of why this is happening, or suggested workarounds? Do you see something I'm missing?

Thanks a lot for any help!


James ............................................................................. James Marshall james@xxxxxxxxxxxxx Berkeley, CA @}-'-,-- "Teach people what you know." ............................................................................. .



Relevant Pages

  • RE: How to prevent duplicate cron jobs?
    ... But what if a cron job exits prematurely, ... I've not done it with perl, but we have several other scripts that have ... We have the scripts output a file with it's PID. ...
    (perl.beginners)
  • Re: Simple Issues with Pod (on verbose and help page without param).
    ... Here is a code which use Getopt::Long to produce a help instruction. ... I also want my code to print out the help message ... $ perl mycode.pl -help. ... -help Print a brief help message and exits. ...
    (perl.beginners)
  • Re: How to stop perl from exiting when stat($_)->size fails
    ... Occasionally it fails although the file exists, and perl ... exits with this error on STDERR: Can't call method "size" on an ...
    (comp.lang.perl.misc)
  • RE: How to prevent duplicate cron jobs?
    ... But what if a cron job exits prematurely, ... I've not done it with perl, but we have several other scripts that have ... We have the scripts output a file with it's PID. ...
    (perl.beginners)
  • Re: Phaser 560 and DCPS problem
    ... How did you get the commands that were sent/rec'd from the sysem to the ... CTRL T gives after going telnet <printer> ... and then exits w/ connection refused ...
    (comp.os.vms)