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

I have a web application which runs under mod_perl, FastCGI and PersistentPerl (if these technologies are supported on the deployment platform). In most circumstances, everything is running fine and dandy, but occassionally I need to kick off a long running task.

What I'd rather do is invoke the logic from a script rather than directly from the web app, and let it run in the background:

system('/path/to/script.pl &');

(I'm ignoring error handling for the purposes of this discussion). The problem is that this works for *nix, but not for Windows. Is there any way of invoking the script in the backgroud that would work for both *nix and windows platforms?

Replies are listed 'Best First'.
Re: Long running task from web app
by friedo (Prior) on Mar 03, 2006 at 22:30 UTC
    For this type of thing I find it's better to use a backend daemon instead of running the process directly from the web server. Use something simple like Proc::Daemon and have it monitor a queue file or database table, and fork off a process to run the requested task. That should work easily on most platforms.
      I'd second friedo's suggestion. I've typically done this sort of thing by having a daemon/service sitting in the background waiting for a signal to start. Then your web app may simply send the signal. I've done it using many techniques:

      Two techniques you can use to let the daemon/service take no CPU:
      1) Use a named pipe, where the daemon/service is blocking while reading the pipe. This is handy when you want to send special commands/arguments to the background task.
      2) Use a mutex. Simple when you don't have to pass params to the background task.

      Two techniques you can use if you don't mind the background daemon/service periodically polling:
      1) Use a plaintext file. Web app creates file with specified name, daemon/service starts job when it notices the file appear.
      2) Put a particular row in a "misc" table, and daemon simply looks for it's entry to appear.

      --roboticus
Re: Long running task from web app
by davidrw (Prior) on Mar 03, 2006 at 23:04 UTC
      Thanks for your reply. The thing is, I don't want to watch the long running process - I just want to initiate it and then forget about it. So I guess I just want a way to background a process without relying on *nix's &

        This is hard to do portably and reliably with the same code. You may want to alternatively fork & exec (on Unix) or use Win32::Process or Win32::Job on Windows, based on the value of $^O.

        -xdg

        Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Long running task from web app
by ikegami (Patriarch) on Mar 03, 2006 at 22:29 UTC
      Thanks. I guess I should mention that I don't want to hang around and wait for the job to complete. I have no interest in comunicating with or monitoring the child process - I just want to kick off the job and let it run .. cos it will take ages, and the user will want to move onto other things. From my understanding of the doco for the modules above, they're all about communicating with the child process

        According to perlipc,

        On most Unix platforms, the CHLD (sometimes also known as CLD) signal has special behavior with respect to a value of 'IGNORE' . Setting $SIG{CHLD} to 'IGNORE' on such a platform has the effect of not creating zombie processes when the parent process fails to wait() on its child processes (i.e. child processes are automatically reaped). Calling wait() with $SIG{CHLD} set to 'IGNORE' usually returns -1 on such platforms.

        The alternative is to do something called "double forking", at least on unix. I'm not sure on the details, but a Super Search or a Google search for this should give you some info.

        But really, in this case, friedo's response is probably the best for you.

Re: Long running task from web app
by Arunbear (Prior) on Mar 04, 2006 at 17:15 UTC
Re: Long running task from web app
by BrowserUk (Patriarch) on Mar 04, 2006 at 17:18 UTC

    The simplest mechanism is

    if( $^O eq 'MSWin32' ) { system 1, 'path/to/script.pl'; } else { ## assume some flavour of *nix system '/path/to/script.pl &'; }

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Cheers. Regarding
      system 1, 'path/to/script.pl';

      I've never seen this before. What does the "1," mean?

        It's a Win32-only extention that causes system to create a detached process.

        I seem to recall that someone recently gave a reference to a document that mentioned it somewhere, but I don't recall who or where :( That said, there is not much to know, pass 1 as the first parameter and system doesn't wait for the command to finish before returning.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.