in reply to Re^2: Fork parent process dies unexpectedly
in thread Fork parent process dies unexpectedly

(everything in this reply is untested)

Your main problem is here:

while (my $conn = $socket->accept) {
Accept failing is not usually fatal and should not terminate your loop. In particular, if you get a signal, accept can return without result with $! set to EINTR. And you get signals when your children die.

This doesn't happen in somewhat older perls since they by default have a setting to restart slow systemcalls (but the problem would reappear in really old perls which didn't yet do that).

In new perls (since 5.8) signals only set a flag and handlers only get executed if the perl dispatcher is in a safe state and sees the flag. But that forced the developers to turn off the restarting of slow systemcalls since otherwise actual running of the signal handler code can be indefinitely delayed (the flag would get set, but since the systemcall gets restarted it still doesn't get to the dispatcher, so nothing gets executed)

On UNIX versions that support it, you could avoid getting child signals at all by using

$SIG{CHLD} = "IGNORE";
But that just sets you up to take the fall when you start handling other kinds of signals.

So just change the loop to something like:

use POSIX qw(EINTR); ... while (1) { my $conn = $socket->accept; if (!$conn) { warn("Accept error: $!" if $! != EINTR; next; } .... }

Replies are listed 'Best First'.
Re^4: Fork parent process dies unexpectedly
by iang (Sexton) on Nov 19, 2005 at 19:36 UTC
    Thanks to everybody that replied. This seems to be working as I want. I will read more about the EINTR signal. When the last child dies the error rasised by $socket->accept is "No child processes". I will look at Net::Server. It looks like what I need, but I am glad I took this approach to start. Again, my many thanks.

    Ian

      (again, everything in this reply is untested. Based purely on the problem description)

      Ah, that one is another result of the current perl handlers. The order of execution is now:

      - signal happens, triggers perl internals - flag for this signal is set by internals - systemcall is interrupted, $! set to EINTR - perl dispatcher sees flag, starts your signal code However, this code happens to change $! - The assign of undef to $conn happens - You check $conn, see its undef and then go look at $!, but you get the $! left by your signal handler, not the older one you really need.
      Solved easily enough by adding
      local $!;
      at the start of your signal handler.

      Personally I consider this a perl flaw/bug though. I think perl should localize $! when it calls the deferred user signal code.