Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical


by flyingmoose (Priest)
on Mar 24, 2004 at 22:40 UTC ( #339577=modulereview: print w/replies, xml ) Need Help??

Item Description: Create and manage processes on Windows & Unix

Review Synopsis:

Review of Proc::Background

Ah, the subject of processes and forking. This brings up many questions in the monastery, so I decided I would add this to the module reviews section each time it came up. Yes, folks, spawning processes and waiting on them doesn't have to be so complicated. Let's look at the problem-space a bit and we will understand why Proc::Background is so cool to have.

The Problem

unix: There are several ways to background a process on Unix, one can fork and exec a system call, one can make a system call using &, and so on. There are also things like Proc::ProcessTable, but again, this can get complicated.

windows: There are also several ways to background a process on Windows, but forking is often implemented wrong on your particular version and should be avoided. There is Win32::Process, but it requires an absolute path to the executable you are trying to run, which can sometimes be hard to acquire when you don't know where that program lies in your path.

The Solution

The above problems can get ugly in a hurry, especially if you are new to Unix (and don't understand fork well), don't want to deal with Win32 modules, or if you want code that works in something other than Unixy environments. This is where Proc::Background comes in. It allows one to not worry about Unix or Windows and to (effectively) manage processes without all of the gory details. In addition, it allows waiting on arbitrary processes and checking on the status of each. Very cool, and even cooler because it is cross platform.

Example Code (borrowed from CPAN)

use Proc::Background; my $proc1 = Proc::Background->new($command, $arg1, $arg2); my $proc2 = Proc::Background->new("$command $arg1 1>&2"); $proc1->alive; $proc1->die; $proc1->wait;

see CPAN for the full list of functions, but those are the basics. Easy, no?

When To Use It

  • When you want clean code that is very short and understandable
  • When you must execute processes in cross-platform code for Windows and Unix
  • When you don't have enough tylenol/advil/beer to deal with Win32::Process
  • When you have to inquire about the status of arbitrary processes or must act upon their states (is process A up? How about B? Now wait for C to finish!)

When Not To Use It

  • When you have Unix buddies you are trying to impress
  • When you have Win32 buddies you are trying to impress
  • When you are trying to keep up your job security by keeping code hard to read :)
  • When you need to execute arbitrary Perl code and not seperate executables
  • If you are using solaris or cygwin. It appears that (per CPAN reports) this may not work there. Your mileage may vary. (I use Linux and Win32 most of the time).
  • Foreground processes? NO, WAIT! It works there too, just use 'wait' method on your process after you invoke it and you have something a little more spiffy than the stock system call. This is at your discretion, of course, this isn't really required.

The Final Word

This module is very useful and is currently in my top 10. It efficiently allows management of any number of processes and allows me to forget (when I feel like it) how fork, exec, and Win32::Process work in Perl -- saving me pain and frustration. It also makes code much more legible due to a clean API, and that is always a good thing in a module.

You can remember how to use it without looking things up, since the API is so basic -- this is goodness. Try it out, unless you are a Unix purist who must always write their own fork code to spawn processes, this should work great for you.

Replies are listed 'Best First'.
Re: Review of Proc::Background
by diotalevi (Canon) on Mar 24, 2004 at 22:53 UTC
    I never thought this module worked all that well. You can't decide whether there is another instance of yourself already running before Proc::Background::Init is run and still be able to send some text back to the console. I ended up switching to Sys::Syslog to get around that problem but it was really a pain at first.

      UPDATE: the poster above this was thinking of Proc::Daemon not Proc::Background, please ignore this entire thread unless you want to see our less-than-interesting path to figuring this out...

      You can't decide whether there is another instance of yourself already running before Proc::Background::Init is run and still be able to send some text back to the console.

      I've always used it for launching processes, not copies of myself (and never Proc::Background inside of a plain fork either), so I have not encountered that problem. For instance, I am doing stuff like launching bzip2 or InstallShield and keeping a Tk app responsive at the same time. Actually, I'm not quite sure how you encountered that particular scenario...

      I'm sure POE has good ways to do this sort of thing as well, but this at least has provided a lightweight mechanism for my uses.

        In the following code sample the database connection cannot be started until after Proc::Background::Init because DBI connections do not survive forks. The fork has to happen before the potentially fatal register_process() because you wouldn't want to write the wrong pid to the process list. This leaves you with no way to report a fatal exit to the console that just started the application.

        exit main( @ARGV ); sub main { eval { Sys::Syslog::openlog( $SYSLOG_IDENT, '', $SYSLOG_FACILITY ); 1; } or Carp::croak( $@ ); Proc::Background::Init(); db_start(); # <- The database connection cannot be established ... } sub db_start { return if $::DBH; main::log_debug( "DBI->connect" ) if $::DEBUG; $::DBH = DBI->connect ( $::DBI_DSN, $::DBI_USER, $::DBI_PASS, { RaiseError => 1, PrintError => 0, AutoCommit => 1 } ) or main::log_emerg( 'emerg', "Error connecting to database: $D +BI::errstr" ); # Potentially fatal - if the process is already running that would + violate the table's constraint system. $::DBH->do( "SELECT register_process( ?, ? )", undef, File::Basename::basename( $0 ), $$ ); return 1; }
Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: modulereview [id://339577]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2023-12-05 06:06 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (25 votes). Check out past polls.