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

Hallo monks,
I'm using

perl5 (revision 5.0 version 8 subversion 0)

on

Linux devvo 2.4.20-8smp #1 SMP Thu Mar 13 17:45:54 EST 2003 i686 i686 i386 GNU/Linux

I don't know if this is really a Perl problem or just a problem of my ignorance about forks.
In any case I've fixed it but I'm curious to know what is going on.
I had a daemon that listened on a socket using IO::Socket::SSL

while accept fork a handler
This was fine, but I needed to do some statistical analysis of connections and, in particular needed to be able to raise alarm events if particular nodes persistently didn't connect at all. To this end, each handler wrote little IPC files to say how they got on with the connection that they were given to handle. I then needed to have the main server periodically hoover up these files and do appropriate things. I thought 'I know, I'll put a call to the monitoring routine in the loop':

while accept fork a handler check any handler results
This would have been fine except in the most important case of failure (no-one connects at all) the loop would block on the accept and the check routine never ran so no alarm would be raised.
Easy, I thought, just fork off a monitor at the start:
fork a monitor to check results while accept fork a handler
And this worked. But it only ever handled one connection and then just appeared to block on the accept, ignoring any attempted connections. If I removed the call to fork the monitor everything worked fine. Odd.
Actually I've missed a crucial bit out of this. I was forking this daemon into background at the start like this:
fork myself into background fork a monitor while accept fork a handler
It occurred to me that it looked as though the 'fork a handler' fork was getting confused about which process was the right one to continue in after the fork. Almost like it was trying to resume in the most-recently-forked 'monitor' fork (which doesn't have the socket open) instead of the fork it came from. So I moved the monitor fork like this:
fork a monitor fork myself into background while accept fork a handler
And this works exactly as I would expect. What I'm curious about is, was the behaviour on the former configuration exactly what a well-informed person should expect or was it buggy aberrant behaviour?

Replies are listed 'Best First'.
Re: Mangled Forks
by shmem (Chancellor) on Jun 04, 2007 at 10:32 UTC
    Without seeing some code it is really difficult to tell what went wrong with your attempts. Check if your forked processes are only executing code which is meant for them. Best practice is to stuff all code for a forked process into a block (or sub) and do an exit just before the end of that block. Don't forget the SIGCHLD handler in the parent, otherwise you will accumulate zombies (=processes that hang around and want to report their exit status to the parent, but the parent just doesn't care).

    I guess it was not "buggy aberrant behaviour" - things well done generally work ;-)

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Mangled Forks
by moritz (Cardinal) on Jun 04, 2007 at 10:18 UTC
    It's no wonder it handled only ever one connection, because varaibles are not shared between forked processes.

    If you want to do that, use threads instead of processes.

    Are you sure you understood how fork works?

Re: Mangled Forks
by liz (Monsignor) on Jun 04, 2007 at 19:28 UTC
    You also might want to take a look at forks.

    Liz