http://qs321.pair.com?node_id=409217

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

I am trying to set up a mod_perl process such that it can fork out a child which can survive the restart of the server. I figured this would be easy enough with minor modifications on the double-fork method, but it doesn't seem to be working. I've tried this:
use Apache::SubProcess; my $pid = fork; if (defined $pid && !$pid) { Apache->request->cleanup_for_exec(); $pid = fork; if (defined $pid && !$pid) { close STDERR; close STDIN; close STDOUT; sleep 100; CORE::exit; } else { CORE::exit; } } waitpid($pid, 0);
Now this does successfuly sever the grandchild from the mod_perl process, inasmuch as its parent process id becomes 1 (child of init). Still, when the mod_perl process gets killed, it still kills the grandchild.

However, if I do the same thing in a perl (not mod_perl) process, minus the Apache::SubProcess and cleanup_for_exec, then it works fine. Killing the grandparent perl process has no impact on the grandchild.

So this made me curious if this was some sort of issue with the apache parent process keeping a record of processes in its process group. I fired up the apache server status page, and it seems to have no clue about the grandchild process. So I don't know why it would be a deliberate signal propogation by the apache server to processes it was only ever briefly associated with.

Of course, there are other ways to accomplish what I want to (via exec'ing), but I'd like to work this out. Anyway, got any ideas on how to do this? Thanks.

------------ :Wq Not an editor command: Wq

Replies are listed 'Best First'.
Re: Keeping grandchild alive when mod_perl process is killed
by Zaxo (Archbishop) on Nov 20, 2004 at 04:54 UTC

    I haven't tried this with Apache/mod_perl, but it might work to call POSIX::setsid() in the first child. That is how daemons liberate themselves from their parent process.

    After Compline,
    Zaxo

      I think it's suppose to be in the grandchild (at least the docs for setsid indicate that you should do it in a child of init), but you're totally right: that's exactly what I was missing. Thanks a bunch, man!
      ------------ :Wq Not an editor command: Wq
        For future archaeologists' sakes (saken? saki?), could you post the working code snippet?

        Thanks,
        mG.

Re: Keeping grandchild alive when mod_perl process is killed
by etcshadow (Priest) on Nov 20, 2004 at 22:36 UTC
    So, for the record, after applying Zaxo's help, this is what you get:
    use Apache::SubProcess; my $pid = fork; if (defined $pid && !$pid) { Apache->request->cleanup_for_exec(); $pid = fork; if (defined $pid && !$pid) { close STDERR; close STDIN; close STDOUT; use POSIX(); POSIX::setsid(); ########## # do long running stuff here ########## CORE::exit; } else { CORE::exit; } } waitpid($pid, 0);
    Although before anyone else plows into this, you should probably look up some info on daemonization to understand it. Also, you'll almost certainly want to reopen STDOUT and STDERR to some log files or something. In short, this is a very small piece of the whole puzzle, so please don't take that snippet of code out of context and think that you've got an entire solution to the problem of long-running processes spawned by a web server.

    Oh, and if your fork fails (returns undef), you should really trap that and deal with it appropriately... I was just posting the miminal amount of code to express my question. I don't mean for this to be really exemplar code.

    ------------ :Wq Not an editor command: Wq