NAME

Parallel::SubFork::Task - Run Perl functions in forked processes.

SYNOPSIS

use Parallel::SubFork::Task;

# Run a some arbitrary Perl code in a separated process
my $task = Parallel::SubFork::Task->start(\&job, @args);
$task->wait_for();

# Create and execute the task (same as above)
my $task2 = Parallel::SubFork::Task->new(\&job, @args);
$task2->execute();
$task2->wait_for();

# Access any of the properties
printf "PID of task was %s\n", $task->pid;
printf "Args of task where %s\n", join(", ", $task->args);
printf "Exit code: %d\n", $task->exit_code;

DESCRIPTION

This module provides a simpler way to run arbitrary Perl code in a different process. This module consists of a fancy wrapper over the system calls fork and waitpid. The idea is to execute any standard Perl function in a different process without any of the inconveniences of managing the forks by hand.

TASK

This module is used to encapsulate a task, i.e. the function to be executed in a different process and it's arguments. In a nutshell a task consists of a reference to a Perl function (\&my_sub) or a closure (sub { 1; }), also known as an anonymous subroutine, and optionally the arguments to provide to that function.

A task also stores some runtime properties such as the PID of the process that executed the code, the exit code and the exit status of the process. These properties can then be inspected by the parent process through their dedicated accessors.

There's also some helper methods that are used to create the child process and to wait for it to resume.

PROCESSES

Keep in mind that the function being executed is run in a different process. This means that any modification performed within that function will only affect the process running the task. This is true even for global variables. All data exchange or communication between the parent the child process has to be implemented manually through standard inter process communication (IPC) mechanisms (see perlipc).

The child process used to executes the Perl subroutines has it's environment left unchanged. This means that all file descriptors, signal handlers and other resources are still available. It's up to the subroutine to prepare it self a proper environment.

RETURN VALUES

The subroutine return's value will be used as the process exit code, this is the only thing that the invoking process will be able to get back from the task without any kind of IPC. This means that the return value should be an integer. Furthermore, since the return value is used as an exit value in this case 0 is considered as successful execution while any other value is usually interpreted as an error.

EXIT

The subroutine is free to raise any exceptions through die or any similar mechanism. If an error is caught by the framework it will be interpreted as an error and an appropriate exit value will be used.

If the subroutine needs to resume it's execution through a the system call exit then consider instead using _exit as defined in the module POSIX. This is because exit not only terminates the current process but it performs some cleanup such as calling the functions registered with atexit and flush all stdio streams before finishing the process. Normally, only the main process should call exit, in the case of a fork the children should finish their execution through POSIX::_exit.

PROCESS WAIT

Waiting for process to finish can be problematic. There are multiple ways for waiting for processes to resume. Each having it's advantages and disadvantages.

The easiest way is to register a signal handler for CHLD signal. This has the advantage of receiving the child notifications as they happen, the disadvantage is that there's no way to control for which children the notifications will happen. This is quite inconvenient because a lot of the nice built-in functions and operators in Perl such as `ls`, system and even open (when used in conjunction with a |) use child processes for their tasks and this could potentially interfere with such utilities.

Another alternative is to wait for all processes launched but this can also interfere with other processed launched manually through fork.

Finally, the safest way is to wait explicitly only for the processes that we know to have started and nothing else. This there will be no interference with the other processes. This is exactly the approach used by this module.

METHODS

A task defines the following methods:

start

Creates and executes a new task, this is simply a small shortcut for starting new tasks.

In order to manage tasks easily consider using use the module Parallel::SubFork instead.

Parameters:

$code: the code reference to execute in a different process.
@args: the arguments to pass to the code reference (optional).

new

Creates a new task, this is simply a constructor and the task will not be started yet.

The task can latter by started through a call to "execute".

In order to manage tasks easily consider using use the module Parallel::SubFork instead.

Parameters:

$code: the code reference to execute.
@args: the arguments to pass to the code reference (optional).

code

Accessor to the function (code reference) that will be executed in a different process. This is what the child process will execute.

This function is expected to return 0 for success and any other integer to indicate a failure. The function is free to raise any kind of exception as the framework will catch all exceptions and return an error value instead.

The function will receive it's parameters normally through the variable @_.

pid

The PID of the process executing the subroutine, the child's PID.

exit_code

The exit code of the task, this is the value returned by exit, POSIX::_exit or return.

status

The exit code returned to the parent process as described by wait. The status code can be inspected through the "WAIT"" in "POSIX macros .

args

The arguments that will be given to the subroutine being executed in a separated process. The subroutine will receive this very same arguments through @_.

This method always return it's values as a list and not as an array ref.

execute

Executes the tasks (the code reference encapsulated by this task) in a new process. The code reference will be invoked with the arguments passed in the constructor.

This method performs the actual fork and returns automatically for the invoker, while the child process will start to execute the code in defined in the code reference. Once the subroutine has finished the child process will resume right away.

The invoker (the parent process) should call "wait_for" in order to wait for the child process to finish and obtain it's exit value.

wait_for

Waits until the process running the task (the code reference) has finished.

The exit status of the process can be inspected through the accessor "exit_code" and the actual status, the value returned in $? by waitpid can be accessed through the accessor "status".

NOTES

The API is not yet frozen and could change as the module goes public.

SEE ALSO

Take a look at POE for asynchronous multitasking and networking.

AUTHOR

Emmanuel Rodriguez, <emmanuel.rodriguez@gmail.com>

COPYRIGHT AND LICENSE

Copyright (C) 2008 by Emmanuel Rodriguez

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.