beemshake has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks. I've run into a problem with perl's accept() function, as called by IO::Socket.pm. Occasionally, a process dies just after accept() is called, such that accept doesn't even return, it just kills the process. I tried putting the call to accept() in an eval so I could catch the error in $@, but no luck, the process still blows up.

While I'd love to supply you with some code to reproduce the problem, I can't, since it's spread through several libs and executables. However, I can show you the offending code, and some run-time info. From IO::Socket, with some debug messages added by me:

printf "PID $$: IO::Socket calling accept(%s, %s)\n", $new, $sock; $peer = accept($new,$sock); printf "PID $$: IO::Socket accept() call returned\n"; return unless $peer;

A successful call:

PID 18943: IO::Socket calling accept(IO::Socket::INET=GLOB(0x833803c), IO::Socket::INET=GLOB(0x879808c))
PID 18943: IO::Socket accept() call returned

An unsuccessful call (with message from SIG{CHLD} handler):

PID 18943: IO::Socket calling accept(IO::Socket::INET=GLOB(0x886d064), IO::Socket::INET=GLOB(0x879808c))
Reaped PID 18943, exit status 14

The script I'm running spawns 3 child processes, which communicate using IO::Socket. The process that eventually dies is doing heavy computing and lots of evals (it's a constraint solver), and, disturbingly, the number of debug messages conditionally compiled in (via constants) does cause variance in the number of messages accepted before it dies. We have tried isolating that process and running it stand-alone, while "stubbing" the other processes by feeding the same input manually, but the problem goes away. The problem comes and goes, but once we get a failing command line it does fail every time, so we can reproduce it.

I should also mention some other potential "issues" with ths code. We see a few "Deep recursion on subroutine blahblah" warnings, as well as some "Use of uninitialized value in bitwise and (&)" warnings, in the code run by this process. However, it has worked many times with these warnings.

I'm running perl 5.8.5 on hosttype "Linux 2.4.9-45lxset34smp GenuineIntel Intel_2791 i686". I tried looking up accept bugs, but the perlbug site won't let me log in (or create a new account), so sorry if this is a known issue. Thanks for any help!

Replies are listed 'Best First'.
Re: accept() dies?
by Ultra (Hermit) on Jun 16, 2005 at 06:03 UTC
    Shouldn't you do something like:
    $main_socket = IO::Socket->new( # params ); # something useful here $new_sock = $main_socket->accept(); # continue
    ?
    IO::Socket advertises accept() as a method not as an exported function; as pointed in the POD, the arguments passed to accept() are wrong.

    Hope this helps ;-)

    Dodge This!
      The OP is calling the accept built-in function, not the method in IO::Socket. And yes, this is questionable.

      Flavio (perl -e 'print(scalar(reverse("\nti.xittelop\@oivalf")))')

      Don't fool yourself.
      Sorry, guess I wasn't clear. That is what I'm doing. My code calls IO::Socket::accept, but in debugging I tracked it into that function, to the call to perl's accept(). That's the code I showed, my hacked version of IO::Socket. IO::Socket::accept's call to perlfunc's accept blows up.
        Oh, sorry for the misunderstanding ...
        Are you passing a timeout to the IO::Socket constructor?
        Also, are you forking after the creation of $sock? if so, all the child processes call accept() upon $sock?
        A .t file that triggers the "bug" would be more than welcome.

        Dodge This!