perlcentosforkapache2.2mod-perl2

How to fork a process from mod_perl2 that kills its parent


I've read numerous threads on this topic and tried just about everything I've encountered: > /dev/null, qx, system, exec, fork, cmd with | (which worked under win32, but now I'm porting to CentOS which uses the prefork MPM), echo | at now, and Proc::Daemon, but I haven't tried Apache2::Subprocess because it looks like it's exactly what I don't want, a thread that's tied to the parent.

Perhaps my situation is different. At the end of a long-running database restore process, I want to restart the very httpd service that the script is running from. Questions of the wisdom of such a design aside, how can I do this? Every method I've tried stops the script as soon as it executes the sudo service httpd stop half of sudo service httpd restart so it never starts again by itself.

The one exception to this is echo | at now, which seemed promising, but if I copy something that works when I do it on the command line and execute it in the mod_perl script, I get a nice successful sounding line like job 1 at 2013-10-31 19:20 but then nothing happens. No shell mail with now -m, no error messages with 2>&1 and/or > /path/with/all/777/perms, no e-mail from my own module that normally does that on any die, no logfile from the same that auto-logs everything. Just a silent fail despite the success line.

In case it helps, here's what service httpd stop runs:

stop() {
        echo -n $"Stopping $prog: "
        kill -TERM `cat ${pidfile}`
        RETVAL=$?
        if [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
        then success
        else failure
        fi
        echo
}

This seemed really simple before and there are so many suggested solutions, but none of them seem to do it. What else is there to check or try?


Solution

  • What finally worked was stealing a hint from Apache2::SubProcess' docs.

    In the mod_perl script, I just do qx($command 2>&1) although other methods might work too.

    Then in script being called in $command, I simply put these lines before the httpd restart:

    use POSIX 'setsid';
    setsid or die "Can't start a new session: $!";
    

    It doesn't ever return to the mod_perl script, which is fine, since I redirect to a log-display page anyway.

    Meanwhile the restart-containing script produces the log correctly through the same old STDOUT redirection I had in there before, and e-mails me if something dies.

    Furthermore, the restart-containing script works normally from the command-line, as it was also designed to do.