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

I have a system that currently has 5-6 Perl daemons running on it 24/7. This system has 2 GB, multi-core, and 4 GB of RAM.

I am working on a different version of this system that will be running on a 500 Mhz 500 MB system (a Soekris Net5501, if knowing the system makes a difference). Both systems are Debian Linux based.

From my limited understanding, if I use fork(), both the parent and child process are running within the same instance of Perl in memory. I remember experimenting with this previously and having to kill zombie processes, but I don't see them remaining anymore after a child thread is killed on my current systems. (Which are running later versions of both Linux and Perl than what I started on.) This is without using $SIG{CHILD} = 'IGNORE'.

I'd like to be able to use one instance of Perl to run all the daemons on the newer system. The ones on the new system will be smaller and have less to do than the ones on the big computer. But I have three main questions about this.

1) On the other system I would create a batch file that was an endless loop. In the loop it'd run the daemon, that way if the daemon was killed, it'd loop back through and run it again. I've seen a number of programs do this. But on Perl, unless I want to keep dealing with zombies, is there a way to tell when a child process has quit?

2) Regarding zombies: Was there some improved coding somewhere or a change in how things are handled in Linux? I don't see zombies showing up when I run tests now.

3) If I use one instance of Perl and fork off a number of child processes instead of running multiple instances of Perl, will that change the priority for the forked processes, or will they likely get the same kind of treatment or CPU time as they would have if I ran them as separate processes?

Thanks for any information on this. I've been Googling, but have yet to find information on this that's clear to me or can tell me why I don't see zombies now when I test fork() and kill off the child processes.

Replies are listed 'Best First'.
Re: Forking vs. A New Process
by tilly (Archbishop) on Jan 24, 2011 at 06:48 UTC
    It seems to me that you need to clarify your understanding of how forking and zombies work on Unix-like systems.

    When you fork(), what you do is split the process into two. Thanks to copy-on-write, the two processes share most of their memory and don't take a lot of resources. Initially one copy is the child and the other is the parent, and the only thing different is one bit saying which is parent and child. (Differences tend to accumulate fairly quickly after that.)

    A zombie is a process that has called exit, but whose parent process has not looked at it to reap its status.

    Preventing zombies is a question of having parents pay attention to the signals from their children. (Or killing the parents, which causes ancestor processes to take responsibility, eventually terminating in the almighty init.)

    Anything you want to do with priorities, you have to do. For instance using setpriority.

Re: Forking vs. A New Process
by chrestomanci (Priest) on Jan 24, 2011 at 07:37 UTC

    Does your limited understanding of fork() come from windows?

    On that platform, fork() is emulated using threads within a process, and if you want to start new processes, then you have to use OS specific calls (Win32::Process).

    As tilly says, on unix like systems, fork clones your process to create two identical copies, one of which gets an arbitary label that says child.

    The issues you have with zobmie processes, are simply that when a process quits, the OS keeps a record of it until the parent tells the OS that it is no longer interested in finding out what happened to it. There are system calls you can make to tell the OS that you are not interested in the fate of your child processes, so that it does not need to keep those records, then you won't get zombies.

    I think the reason they are known as zombies, is untill they are reaped, they take up an entry in the process table, and on some older unixes, that table had limited space, so thousands of zombie processes could hurt performance, or even prevent new useful processes from starting.

      Actually, my limited understanding of fork() is from being self taught and not having time to explore anything that wasn't directly related to a paycheck until recently.

      Thanks for the info -- it's quite helpful and it makes it sound simpler than I thought it was.

Re: Forking vs. A New Process
by JavaFan (Canon) on Jan 24, 2011 at 09:08 UTC
    If I use one instance of Perl and fork off a number of child processes instead of running multiple instances of Perl, will that change the priority for the forked processes, or will they likely get the same kind of treatment or CPU time as they would have if I ran them as separate processes?
    Note that on a Unix system, after the system has initialized itself, the kernel starts a single process, typically called init. Every other process started since saw light using fork. If you run "separate processes", it's fork (followed by exec) that creates those processes.

    So, there's no difference in the priority new instances will have.

Re: Forking vs. A New Process
by cdarke (Prior) on Jan 24, 2011 at 10:27 UTC
    fork off a number of child processes instead of running multiple instances of Perl

    Modern UNIXs, Linux, and even Windows, share read-only code pages. So although there appears to be multiple instances of perl running, the code is actually only loaded once. Data pages are not shared (usually) and those will be unique to each process. Threads of execution can share data pages as well, but that involves multi-threading and is a whole different game to forking child processes.

    Aside from your zombie problem (use wait or waitpid), I am not clear what the problem is that you are trying to solve.