CHAPTER 21

Processes, Signals, and Threads

In this chapter, we look at managing multiple strands of execution within a single application, both with multiple separate processes and with lighter-weight threads. We also cover the related subject of communicating between processes, both within the same application and between applications. In particular, we examine signals and interprocess communication, also known as IPC.

Signals are the operating system's basic mechanism for indicating error conditions and other events asynchronously. We can receive them, for example, as a result of errors in low-level system calls or abnormal termination of socket filehandles. Unless we handle it or state that we wish to ignore it, such a signal will terminate the running application. Ignoring a signal is easy but not always wise, so in this chapter we will see how to write special subroutines called signal handlers to manage signals sensibly. We can also raise signals against other processes, either once in the same application or elsewhere. Not all signals are errors. On Unix platforms, for example, we can use an alarm signal to trigger an event over a period of our choosing.

In the main part of the chapter, we look at writing Perl applications that manage multiple concurrent strands of execution. First we examine creating and handling multiple separate processes. While this is chiefly of interest to Unix programmers, Perl now has quite credible emulation for multiprocessing applications under Windows too. One of the major problems with multiple processes is getting information between them, so we also look at message queues, semaphores, and shared memory, three different solutions to the problem of interprocess communication.

After processes we look at threads, specifically the new interpreter threads introduced with Perl 5.8. While processes exist in relative isolation, with completely separated data and execution environments, threads share everything within the same process. This makes them very lightweight by comparison and easy to share data between. In most languages, it also makes them much trickier to program since it is easy for threads to overwrite the same data. However, interpreter threads enable Perl to keep data used by different threads partitioned away from each other unless we specify that data is to be shared. This greatly simplifies the task of programming threads and making most Perl modules thread-compatible even if they have no special knowledge or understanding of them.

Signals

Much like hardware interrupts, signals are exceptional events that happen independently of whatever code a program happens to be executing at the time. They are said to be "out of band," since they also cannot be deferred for handling at a later point in time. Either the program recipient of a thread handles it, or the operating system will handle it by terminating the program.

Typically, the operating environment defines default triggers and behaviors for most signals. A Unix shell, for instance, maps some signals to key sequences, such as KILL to Ctrl-C, and STOP to Ctrl-Z. Other processes, as well as the kernel, have the ability to send signals to any designated process.

Every process keeps an index table of each possible signal and its response to each. Whenever a process receives a signal, it stops normal execution and executes the behavior defined for that signal. Depending on the signal, that behavior may be to take some action and then return control back to the interrupted routine. Alternatively, the response might be to do some cleaning up and exit the program or to explicitly ignore the signal.

Perl allows the programmer to redefine the behaviors of most signals in any of these ways as necessary. The signal index is stored in Perl as the hash variable %SIG, with the key value being the signal name and the value being either

  • A code reference to a subroutine to execute
  • A scalar return value

By assigning various values to signals in the hash, we can control how an application responds to different signals. To elaborate a little on what kind of signals we have available, we can dump out a list of them by printing out the keys of the %SIG hash:

> perl -e "print join q/ /,sort keys %SIG"

At the system level, each signal is denoted as an integer, rather than the name we see here. If we need to cross-reference the numeric and names, we can discover them via kill -l (provided we're on a Unix platform, of course) or through the position of the name in Perl's Config variable sig_name, which is a space-delimited string:

#!/usr/bin/perl
# siglist.pl
use warnings;
use strict;

use Config;

my @signals = split ' ', $Config{sig_name};
for (0..$#signals) {
    print "$_ $signals[$_] " unless $signals[$_] =˜ /^NUM/;
}

This generates a list of all signals and their associated number, skipping over real-time signal numbers beginning NUM (in the range between RTMIN and RTMAX):


0 ZERO
1 HUP
2 INT
3 QUIT
4 ILL
5 TRAP
6 ABRT
7 BUS
8 FPE
9 KILL
10 USR1
...

Many of these signals are obscure, unlikely, or only occur if we have certain features enabled. The signal SIGPWR, for example, applies to power failure situations and SIGIO occurs only with filehandles set to asynchronous mode using O_ASYNC. The most commonly used signals are as listed in Table 21-1 (but note that not all of these signals work on non-Unix platforms).

Table 21-1. Standard Signals and Their Meanings

Name Key Meaning
SIGHUP HUP Hangup
Controlling terminal or process has terminated (for example, a modem, hence "hang up"). Often redefined in daemons to tell them to reread their configuration files and restart operations.
SIGINT INT Interrupt
Instruct the process to interrupt what it is doing and exit. This signal is trappable (which means we can redefine its handler) so that a process can perform any necessary clean-up before doing so. Pressing Ctrl-C on the keyboard is often the manual way to send this signal.
SIGQUIT QUIT Quit
A higher priority signal to shut down and, depending on the system's configuration, may produce a core dump. This signal, too, is trappable.
SIGKILL KILL Kill
An explicit command to tell the process to immediately exit. This signal is not trappable. (Would we really want to take away the kernel's ability to terminate runaway processes?)
SIGUSR1 USR1 User-defined signal
While this signal is never used by the kernel, the default behavior for any process receiving the signal is to exit.
SIGUSR2 USR2 User-defined signal
A second signal for process definition. Like USR1, the default behavior is to exit.
SIGPIPE PIPE Broken pipe
A pipe that a process was either reading from or writing to has been closed by the other end.
SIGALRM ALRM Alarm
An alarm timer for this process has expired. Not supported on Microsoft platforms.
SIGTERM TERM Terminate
Like INT, this instructs the process to exit and is trappable. This signal has a higher priority than INT, but lower than QUIT and KILL.
SIGCHLD CHLD Child exit
A child process has exited.
SIGFPE FPE Floating-point exception
The floating-point processor was asked to perform an illegal operation.
SIGSEGV SEGV Invalid memory reference
An attempt was made to read or write an invalid address in memory.
SIGCONT CONT Continue
Resume execution if stopped by a STOP signal.
SIGSTOP STOP Stop
The process is halted until it receives a CONT, at which point it resumes operational. This signal is not trappable.
SIGIO IO Asynchronous IO event
If a filehandle is set for asynchronous operation (O_ASYNC), this signal is raised whenever an event (for example, more input) occurs on it.
SIGWINCH WINCH Window changed
The window or terminal in which the console of a process is running has changed size (the user resizing a window can do this). Chapter 15 discusses this in more detail.

For a complete list of signals, there is no substitute for the system documentation (usually man 7 signal on Unix). Even on Unix, some signals are platform dependent. The same documentation should inform us of the default behavior of each signal. Regardless, by manipulating the contents of the %SIG hash, we can override these defaults for most signal types and install our own mechanisms for handling signals.

Safe vs. Unsafe Signals

Between Perl 5.6 and 5.8, the way Perl handled signals was overhauled significantly. In the old implementation, a signal could interrupt Perl in the middle of executing an opcode. This made it very tricky to handle signals safely, especially if any significant manipulation of Perl's state happened as a result of the signal. In such cases, the interpreter could find itself in an inconsistent state, with unpredictable consequences.

Perl 5.8 introduces so-called safe signals, which guarantee that signals will only be delivered to the running application in between opcodes. This means that if Perl is busy reading or writing to a filehandle, it will finish the current IO operation before handling the signal. Similarly, if the program is in the middle of a sort operation, the operation will complete first.

The advantage of safe signals is that signal handling is much more robust. The disadvantage is that since some operations can take a long time, receipt of a signal may not occur quickly. For the most part, this is not an issue, but in a few applications, it might be more important to handle a signal quickly than try to keep Perl happy (typically this would be situations where the program is always going to terminate as a result of the signal and never attempt to resume). For these applications, we can set the environment variable PERL_SIGNALS to unsafe:

> PERL_SIGNALS=unsafe immediatesignalapp.pl

To explicitly request safe signals, we can set the variable to safe instead. Prior to Perl 5.8, this variable has no effect (and signals are always "unsafe").

Signal Handling

A string or subroutine reference may be set as values of the %SIG hash to control what happens when a given signal is received:

Value Action
DEFAULT or undef Perform the default behavior as determined by the system.
IGNORE Instruct the process to take no action in response to the signal. Untrappable signals are unaffected by this setting (such as KILL).
&subreference
sub { codeblock }
If a subroutine reference or an anonymous subroutine is set as the value of a signal, then it is called whenever that signal is received. We can then decide how to handle it ourselves, including ignoring it, raising a different signal, dying, and so on.
subroutine If the name of the subroutine is set as a string, this will be evaluated as &main::subroutine when the signal is received.

For example, to ignore SIGPIPE signals, we would put the following:

$SIG{PIPE} = 'IGNORE';

To restore the default handling for SIGINT signals:

$SIG{INT} = 'DEFAULT';

To find out the current setting of SIGALRM (remembering that undef is equal to DEFAULT):

$alarming = $SIG{ALRM};

To set a subroutine as a signal handler:

$SIG{USR1} = &usr1handler;

The last of these is, of course, the most interesting. Signal handlers, when called, receive the name of the signal that called them as an argument, so we can assign multiple signals to the same handler or handle each signal individually.

$SIG{HUP}  = &handler;
$SIG{STOP} = &handler;
$SIG{USR1} = &handler;

If we set a text string that is not DEFAULT or IGNORE, then it is taken as a symbolic reference to a subroutine in the main (not the current) package. So be careful about spelling. Thus

$SIG{INT} = 'DEFLAT';

actually means

$SIG{INT} = &main::DEFLAT;

This will silently fail unless we are using the -w flag with Perl, in which case it will merely complain on STDERR that the handler DEFLAT is undefined. Although this is a perfectly legal way to set a signal handler, the fact that it defaults to the main package can cause confusion when handling signals inside packages—even if the package defines a subroutine with the same name, it won't get called. Note also that though this is a form of symbolic reference, it is not trapped by the use strict refs pragma. Conversely, if we try to set a signal that does not exist, Perl will complain with an error, for example:


No such signal SIGFLARE at...

A practical example for redefining trappable signals would be when our program creates temporary files. A well-behaved program should clean up after itself before exiting, even when unexpectedly interrupted. In the following example, we will redefine the INT handler to remove a temporary PID file before exiting. This will keep the program from leaving PID files around when the user interrupts the program with a Ctrl-C:

$SIG{INT} = sub {
    warn "received SIGINT, removing PID file and exiting. ";
    unlink "$ENV{HOME}/.program.pid";
    exit 0;
};

The die and warn Pseudo-Handlers

In addition to the standard signals, the %SIG hash also allows us to set handlers for Perl's error reporting system, specifically the warn and die functions together with derivatives of them like carp and croak (supplied by the Carp module). These are not true signal handlers but hooks into Perl's internals, which allow us to react to events occurring within Perl. The %SIG hash makes a convenient interface because, aside from some minor differences in behavior, they operate very similarly to signals.

Neither the warn or die hooks are present as keys in the %SIG hash by default—we have to add them:

$SIG{__WARN__} = &watchout;
$SIG{__DIE__}  = &lastwillandtestament;

Both handlers may customize the error or warning before passing it on to a real warn or die (the action of the handler is suppressed within the handler itself, so calling warn or die a second time will do the real thing). A warning handler may choose to suppress the warning entirely; die handlers, however, cannot avert death, but only do a few things on its deathbed, so to speak. See Chapter 16 for more on die and warn, and registering handlers for them.

The hook mechanism is not extensible; the __ prefix and suffix merely distinguish these special handlers from true signal handlers. They do not, however, allow us to create arbitrary signals and handlers.

Writing Signal Handlers

Signal handlers are just subroutines. When they are called, Perl passes them a single parameter: the name of the signal. For example, here is a program containing a very simple signal handler that raises a warning whenever it receives an INT signal, but otherwise does nothing with it:

#!/usr/bin/perl
# inthandler1.pl
use warnings;
use strict;

sub handler {
    my $sig = shift;
    print "Caught SIG$sig! ";
}

# register handler for SIGINT
$SIG{INT} = &handler;

# kill time
while (1) { sleep 1; }

Note that since the handler handled the exception, the program does not exit. If we still want the handler to exit after performing whatever other actions we need done, we must add the exit command to the end of our handler. Here is another handler that implements this scheme, using a private counter. It will catch the first two signals but defer to the normal behavior on the third reception:

#!/usr/bin/perl
# inthandler2.pl
use warnings;
use strict;

{
    # define counter as closure variable
    my $interrupted = 0;

    sub handler {
        foreach ($interrupted) {
            $_ == 0 and warn("Once..."), $interrupted++, last;
            $_ == 1 and warn("Twice..."), $interrupted++, last;
            $_ == 2 and die ("Thrice!");
        }
    }
}

# register handler for SIGINT
$SIG{INT} = &handler;

# kill time
while (1) { sleep 1; }

A few platforms (BSD systems, typically) cancel signal handlers once they have been called. If we want these systems to be maximally portable, we have to reinstall the handler before we exit it, if we wish it to be called again:

handler {
    $sig = shift;

    # reinstate handler
    $SIG{$sig} = &handler;

    ... do stuff ...
}

To prevent another signal from coming in before we have redefined it, we will do that first in every handler. Since this does no harm even on platforms that do not need it, it is a good piece of defensive programming if we are worried about portability.

Avoiding Overcomplex Handlers

The preceding handlers are good examples of signal handlers in the sense that they do very little. Signals implicitly herald a critical event, so executing complex code, and especially anything that causes Perl to allocate more memory to store a value, is a bad idea.

Avoiding Memory Allocation

For example, the following signal counting handler is not a good idea; it allocates a new key and value for the hash each time a signal it has not seen previously arrives.

%sigcount;

sub allocatinghandler {
    $sigcount {$_[0]}++;
}

This modified version is fine though, as we have guaranteed that all the keys and all the values of the hash already exist, so no new memory needs to be allocated within the handler:

%sigcount = map { $_ => 0 } keys %SIG;

sub nonallocatinghandler {
   $sigcount{$_[0]}++;
}

The rule of thumb for any signal handler is to do the absolute minimum necessary.

Uninterruptible Signal Handlers

Unlike the warn and die hooks, real signal handlers do not suppress signals while they are running, so if we want to avoid being interrupted a second time while we are still handling a signal, we have to find a way to avoid further signals. One way to do this is simply disable the handler for the duration of the handler:

sub handler {
    $SIG{$_[0]} = 'IGNORE';
    ... do something ...
    $SIG{$_[0]} = &handler;
}

A better way is to localize a fresh value for the signal value in $SIG using local. This has the same effect as reassigning it explicitly, but with the advantage that the old value is restored immediately on exiting the handler without our intervention:

sub handler {
    local $SIG{$_[0]} = 'IGNORE';

    ... do something...
}

We can suppress signals in normal code using the same principles, for instance, by temporarily reassigning a signal to a new handler or value. We can do that by either making a record of the old one or using local to suppress it if we happen to be in a section of code that is scoped appropriately:

$oldsig   = $SIG{INT};
$SIG{INT} = 'IGNORE';

... code we do not want interrupted ...

$SIG{INT} = $oldsig;

As always, these techniques only work on trappable signals.

Aborting System-Level Operations

On many versions of Unix, as well as a few other platforms, signals that occur during some system calls, and in particular during input and output operations, may cause the operation to restart on the return from the signal handler. Frequently, we would rather abort the whole operation at this point, since resuming is likely to be either pointless or plain wrong. Unfortunately, the only way to abort the interrupted code from inside a signal handler is to use die or CORE::exit. Moreover, to be able to resume normal execution at a point of our choice rather than jump into a die handler or exit the program, we have to put the die (or rather, the context of the die) inside an eval, since that will exit the eval and resume execution beyond it. So the code we want to abort must all be inside an eval:

sub handler {
    $SIG{$_[0]} = 'DEFAULT';
    die;
}

$result = eval {
    $SIG{INT} = &handler;
    ...read from a network connection...
    $SIG{INT} = 'DEFAULT';
    1;   # return true on completion
}

warn "Operation interrupted! " unless $result;

If the code in the eval completes successfully, it returns 1 (because that is the last expression in the eval). If the handler is called, the die causes the eval to return undef. So we can tell if the handler was called or not by the return value from eval, and therefore we can tell if the code was interrupted. We can vary this theme a little if we want to return an actual result from the eval; so long as we do not need to validly return a false value, we can always use this technique. Note that even though the die itself is not in the eval, the context in which it is called is the eval's context, so it exits the eval, not the program as a whole.

This approach also works for setting and canceling alarms to catch system calls that time out; see the later section "Alarms" for more information.

Flexibly Installing Signal Handlers

We have already seen how to install a signal handler by hand; simply set the value of the relevant signal in the signal hash:

$SIG{INT} = &handler;

While fine for a single signal, this is cumbersome for handling many of them. One way to set up multiple signals is to assign a new hash to %SIG, for example:

%SIG = (%SIG, INT => IGNORE, PIPE => &handler, HUP => &handler);

There is, however, a better way, with the sigtrap pragmatic module. This takes a list of signal actions and signals, and assigns each signal the action that immediately preceded it. sigtrap provides two handlers of its own: a stack-trace handler, the default action, and die, which does what it implies. It also provides several keywords for common groups of signals, as well as a keyword for currently unassigned signals.

The default action is stack-trace, so the following three pragmas all have the same effect; normal-signals is the group comprising the SIGINT, SIGHUP, SIGPIPE, and SIGTERM signals:

use sigtrap qw(INT HUP PIPE TERM);
use sigtrap qw(stack-trace INT HUP PIPE TERM);
use sigtrap qw(stack-trace normal-signals);

Alternatively, we can choose to set a die handler. Here are two examples of using die with the signals that sigtrap categorizes under error-signals:

use sigtrap qw(die ABRT BUS EMT FPE ILL QUIT SEGV SYS TRAP);
use sigtrap qw(die error-signals);

We can also supply our own handler, by prefixing it with the keyword handler:

use sigtrap qw(handler myhandler ALRM HUP INT);

If we want to be sure the handler exists before installing it, we can drop the qw and use a subroutine reference in a regular list:

use sigtrap handler => &myhandler, qw(ALRM HUP INT);

We may assign different handlers to different signals all at the same time; each signal is assigned the handler before it in the list. The signals at the front are assigned stack-trace if the first item in the list is not die or a handler of our own devising:

use sigtrap qw(
    stack-trace normal-signals ALRM USR2
    die error-signals
    handler usrhandler USR1 USR2
    die PWR
    handler inthandler INT HUP
);

We can specify as many handlers and signals as we like. In addition, later assignments supplant earlier ones, so handler inthandler INT HUP replaces the assignment to stack-trace of these signals in the first line (in the guise of normal-signals). If we want to assign a handler to all signals only if they have not already been assigned or ignored, we can precede the signals we want to trap conditionally with the untrapped keyword. For example, to call the stack-trace handler for normal signals not already trapped:

use sigtrap qw(stack-trace untrapped normal-signals);

The opposite of untrapped is any; this cancels the conditional assignment of untrapped:

use sigtrap qw(stack-trace untrapped normal-signals any ALRM USR1 USR2);

If sigtrap is not passed any signal names at all, it defaults to a standard set that was trapped in previous incarnations of the module. This list is also defined as old-interface-signals. The following are therefore equivalent:

use sigtrap qw(stack-trace old-interface-signals);
use sigtrap;

Sending Signals

The traditional Unix command (and C system call) for sending signals is kill, a curious piece of nomenclature that comes about from the fact that the default signal sent by the kill command was 15--SIGTERM, which caused the program to exit. Despite this, we can send any signal using Perl's kill function.

The kill command takes at least two arguments. The first is a signal number or a signal name given as a string. The second and following arguments are the IDs of processes to kill. The return value from kill is the number of processes to which a signal was delivered (which, since they may ignore the signal, is not necessarily the number of processes that acted on it):

# tell kids to stop hogging the line
kill 'INT', @mychildren;

# a more pointed syntax
kill INT => @mychildren, $grandpatoo;

# commit suicide (die would be simpler)
kill KILL => $$;   # $$ is our own process ID
kill (9, $$);      # put numerically

# send our parent process a signal
kill USR1 => getppid

Sending a signal to a negative process ID will send it to the process group of that process (including any child processes the process may have, and possibly the parent process that spawned it too, unless the process used setpgrp). For example, this instruction will send an HUP signal to every other process in the same process group:

kill HUP => -$$;

The HUP signal in particular is useful for a parent process to tell all its children to stop what they are doing and reinitialize themselves. The Apache web server does exactly this in forked mode (which is to say, on Unix but not Windows) if we send the main process a HUP. Of course, the main process does not want to receive its own signal, so we would temporarily disable it:

sub huphandler {
    local $SIG{HUP} = 'IGNORE';
    kill HUP => -$$;
}

The signal 0 (or ZERO) is special. It does not actually send a signal to the target process or processes at all but simply checks that those process IDs exist. Since kill returns the number of processes to which a signal was successfully sent, for signal 0 it reports the number of processes that exist, which makes it a simple way to test if a process is running:

kill(0 => $child) or warn "Child $child is dead!";

Alarms

Alarms are a particularly useful kind of signal that is issued whenever an internal timer counts down to zero. We can set an alarm with the alarm function, which takes an integer number of seconds as an argument:

# set an alarm for sixty seconds from now
alarm 60;

If the supplied number is zero, the previous alarm, if any, is canceled:

# cancel alarm
alarm 0;

Setting the alarm will cause the process to exit (as per the default behavior of the signal), unless we also set a new handler for the signal:

alarmhandler {
   print "Alarm at ", scalar(localtime), " ";
}

$SIG{ALRM} = &alarmhandler;

Please note that specifying a time interval does not mean that the timer will raise a SIGALRM in exactly that interval. What it says is that sometime after that interval, depending on the resolution of the system clock and whether our process is in the current context, a signal will be sent.

A Simple Use of Alarms

We can only ever have one alarm active at a time, per process, so setting a new alarm value resets the timer on the existing alarm, with zero canceling it as noted previously. Here is a program that demonstrates a simple use of alarms, to keep reprompting the user to input a key:

#!/usr/bin/perl
# alarmkey.pl
use strict;
use warnings;

use Term::ReadKey;

# Make read blocking until a key is pressed, and turn on autoflushing (no
# buffered IO)
ReadMode 'cbreak';
$| = 1;

sub alarmhandler {
    print " Hurry up!: ";
    alarm 5;
}
$SIG{ALRM} = &alarmhandler;
alarm 5;

print "Hit a key: ";
my $key = ReadKey 0;
print " You typed '$key' ";

# cancel alarm
alarm 0;

# reset readmode
ReadMode 'restore';

We use the Term::ReadKey module to give us instant key presses without returns and set $| = 1 to make sure the Hurry up! prompt appears in a timely manner. In this example, the alarm 0 is redundant because we are about to exit the program anyway, but in a larger application this would be necessary to stop the rest of the program being interrupted by Hurry up! prompts every five seconds.

Using Alarms to Abort Hung Operations

We can also use alarms to abort an operation that has hung or is taking too long to complete. This works very similarly to the eval-and-die example we gave earlier for aborting from a section of code rather than continuing it—this time we use alarms instead to catch an interrupt. Here is a code snippet that aborts from an attempt to gain an exclusive lock over the file associated with the filehandle HANDLE if the lock is not achieved within one minute:

sub alarmhandler {
    die "Operation timed out!";
}

sub interrupthandler {
    die "Interrupted!";
}

$SIG{ALRM} = &alarmhandler;
$SIG{INT} = &interrupthandler;

$result = eval {
    # set a timer for aborting the lock
    alarm 60;

    # block waiting for lock
    flock HANDLE, LOCK_EX;

    # lock achieved! cancel the alarm
    alarm 0;

    ... read/write to HANDLE ...

    flock HANDLE, LOCK_UN;
    1;   # return true on completion
}

warn @_ unless $result;

The alternative approach to this is to turn the lock into a nonblocking lock, then check the return value, sleep for a short while, and then try again. The signal approach is more attractive than this solution in some ways, since it spends less time looping. It is, though, limited by the fact that we can no longer use an alarm for any other reason until we have stopped using the alarm here for this purpose.

POSIX Signal Functions

Before leaving the subject of signals, some programmers may find it useful to examine the sigaction, sigprocmask, sigpending, and sigsuspend functions provided by the POSIX module. These provide a Perl interface to the standard C library functions of the same name, but with the addition of the POSIX::SigAction and POSIX::SigSet object classes to simplify the creation and manipulation of the underlying C language structures. As of Perl 5.8, sigaction is an atomic operation and can also take an argument of a code reference, DEFAULT or IGNORE, just like the %SIG hash.

In general, there should be no need to use these functions over Perl's built-in signal support (which in any case maps down to them on platforms where they are supported). But for certain cases, such as XSUB programming, the subject of Chapter 20, they might come in useful. See the POSIX manual page for details (the object classes are documented near the end) and the sigaction manual page on supporting platforms.

Starting New Processes

Perl supports the creation of new processes through the fork function, which is an interface to the operating system's underlying fork function. Forking, a pre-Unix concept, is universal on all Unix-like operating systems. Other platforms like Windows (and pre-OS X Macintosh) use a thread-based model and have no native equivalent of fork. Instead, Perl provides an emulation of fork that allows us to "fork" a new process even though the operating system does not understand the concept in those terms. (From Perl 5.8, interpreter threads are used to implement fork. Since interpreter threads do not automatically share data, they are very good at pretending to be forked processes. That said, if we can guarantee Perl 5.8 or better, we should be able to use threads instead on both platforms anyway.)

The fork function spawns a clone of itself, creating a child process (the original process is called the main or parent process). The cloning is total, as the child shares the same application code and has its own copies of every variable and filehandle. After the fork, there are two near-identical copies of the original process running, the only immediate difference being the return value from fork. For the child, it is zero. For the parent, it is the process ID of the child if the fork was successful, or undef if not. As a result, fork is always found in close proximity to an if statement, for example:

if ($pid = fork) {
    print "Still in the parent process - we started a child with ",
      "process ID $pid ";
} else {
    print "This is the child process ";
    # terminate child and return success (zero) to the parent
    exit 0;
}

What the preceding example does not do, though, is check the return value for a failure of the fork operation. If the fork failed entirely, it will return undef, and we should always check for this possibility (which might occur if the system has reached a limit on processes or does not have enough memory to create the new process). So, we can check it using defined:

$pid = fork;
die "Failed to fork: $! " unless defined $pid;
if ($pid) {
    # parent
    ...
} else {
    # child
    ...
}

Replacing the Current Process

We can replace the current process with a completely different one by using the exec function. This replaces the current process in its entirety with the external command supplied as the argument. Even the original process ID is taken over by the new process:

exec 'command', @arguments;

While exec does have uses in a single-processing application, it is more often used with fork to run an external command as a subprocess of the original application. We will show some examples of this in action a little later in the chapter.

Code never needs to check the return value from exec, since if it succeeds the original process will not be there to return a status to in any case. The only time that a program will continue past an exec is if the exec fails:

exec @command;           # hand over to the next act
die "Exec failed: $! "; # exec must have failed

Several of Perl's built-in functions perform automatic fork+execs. These include the system and backtick functions and certain variants of open. We cover all of these later on in the chapter.

Process IDs

The process ID of the current process can always be found from the special variable $$ (also called $PID or $PROCESS_ID with the English module loaded):

print "We are process $$ ";

For Unix, a child process can find the process ID of the parent process that created it with the getppid function (this is not implemented on Windows as it is not meaningful):

$parent = getppid;
print "Our parent is $parent ";

This allows us to use kill to send a signal to the parent process:

kill "HUP", $parent;

On Windows, there is one caveat to be aware of: handles (the Windows equivalents of Unix PIDs) are unsigned 32-bit integers, while Perl's 32-bit integers are signed. Due to this, handles are occasionally interpreted as a negative integer. This interferes with the semantics of signals, where any signal sent to a negative integer goes to the entire process group, not just a specific process, with rather different results than those desired. Process groups are explained in more detail in the next section.

Process, Groups, and Daemons

Whenever a parent process uses fork (either directly or implicitly) to create a child, the child inherits the process group of the parent. The significance of process groups comes in when signals are sent to a group rather than a single process. If it is intended to be an independent process, then the parent may have its own group ID (which is generally the same as its process ID); otherwise, it will have inherited the process group from its own parent.

We can find the process group of a process by using the getpgrp function (like getppid, this is not implemented on Windows or some other non-Unix platforms), which takes a process ID as an argument. To find our own process group, we could write

$pgid = getpgrp $$; #but...

We can also supply any false value, including undef, to get the process group for the current process. This is generally a better idea because not all versions of the underlying getpgrp function are the same, and the only value they have in common is 0. Since Perl maps directly to the underlying function, only 0 is truly portable:

$pgid = getpgrp 0; #...these are better
$pgid = getpgrp;

We usually do not need to find out the process group, since we already know the child will be in the same group as the parent. What we often want to do, however, is change the group to isolate a child from the parent. We can do this with setprgrp, which takes a process ID and a process group ID as arguments:

setpgrp $pid, $pgid;

In practice, the only process we ever want to change the group for is our own, when we want to divorce a child process from the fate of its parent. Specifically, this insulates the former child from any signals sent to the process group of the parent, so the child will live on even if the parent terminates (and signals its children to do so also). Such child processes are said to be daemons, running independently of the original process that created them.

While in theory we can join any existing group, we generally want to create our own group. Process group IDs are just numbers, and they usually have the same value as the process ID that owns that group. To put ourselves in our own group, therefore, we simply need to give ourselves a process group ID that is equal to our process ID:

setpgrp $$, $$;

Just as before, we can use a false value for both IDs to default to the current process ID, so we can also say

setpgrp 0, 0;

Or even just the following (though not quite as portable):

setpgrp;

Both calls will put the child process into its own group. By doing this, we isolate the child from the process group that the parent originally belonged to. Here is a quick example of a daemon that performs the role of a backseat driver (that is, it keeps shouting out directions when we're trying to concentrate):

#!/usr/bin/perl
# backseat.pl;
use warnings;
use strict;

if (my $pid = fork) {
   print "Backseat daemon started with ID $pid ";
   sleep 1;    # give child time to leave group
   kill 9,-$$; # parent suicides gratuitously
}

setpgrp 0, 0;

# child loops in background
while (1) {
   alarm 60;
   foreach (int rand(3)) {
      $_ == 0 and do { print("Go Left! ");       last };
      $_ == 1 and do { print("Go Right! ");      last };
      $_ == 2 and do { print("Wait, go back! "); last };
   }
   sleep rand(3)+1;
}

This is a simplistic example, so there is only one child process. If the parent just exited gracefully, then the child would simply transfer its affections to the init process (PID 1 on most Unix platforms). However, this parent is badly behaved and kills itself and all its children by sending signal 9 (SIGKILL) to its process group. The child survives, however, because by the time the parent does this, it has dissociated itself from the group and does not receive the signal. If we comment out the setpgrp line, the child dies when the parent does and the daemon is not created.

If we do not want to print a friendly message, we can also simplify the fork statement to just

fork and exit;   # isn't self-documenting code great?

Handling Children and Reaping Exit Codes

When a child exits, the operating system keeps a record of its exit status and retains the child process in the process table. The exit status remains until the parent recovers, or reaps it. If we fail to do this, the dead children turn into zombies when the parent exits (no, really—this is all serious Unix terminology, honest) and hang around the process table, dead but not buried. Using the ps command on a system where this is happening reveals entries marked zombie or defunct.      

Perl's built-in functions (other than fork) automatically deal with this issue for us, so if we create extra processes with open, we do not have to clean up afterwards. For fork and the IPC::Open2 and IPC::Open3 modules (both of which we cover later), we have to do our own housekeeping.

Waiting for an Only Child

To reap an exit status, we use either the basic wait or more complex waitpid functions. If we, as the parent process, want to wait for a child to finish before continuing, then there is no problem, we simply use the wait function to cease execution until the child exits:

# fork a child and execute an external command in it
exec @command unless fork;

# wait for the child to exit
$child_pid = wait;

The process ID of the child is returned by wait, if we need it, not the exit status. Instead, we find it in $?.

Getting the Exit Status

When wait returns, it sets the exit code of the child in the special variable $?. As we covered back in Chapter 16, this is a 16-bit value comprised of two 8-bit values, the exit status in the top half and the signal that caused the child to exit (if any) plus the coredump flag in the bottom half. (This is incidentally identical to the value returned by the Unix wait system call.) To get the actual exit code and signal number, we therefore need to use

my $exitsig = $? & 127;   # signal is lower 7 bits
my $cored   = $? & 128;   # coredump flag
my $exitcode = $? >> 8;   # exit code is upper 8 bits

If we import the appropriate symbols from the POSIX module, we can also use some convenience functions (with the same names as the macros familiar to C programmers) to extract these values:

use POSIX qw(:sys_wait_h);

$exitsig = WSTOPSIG($?);
$exitcode = WEXITSTATUS($?);

Note The POSIX module also contains a few other handy functions in the same vein; we list them all briefly at the end of the section.


Only one of the exit codes and the signals will be set, so for a successful exit (that is, an exit code of zero), $? will be zero too. This is a convenient Boolean value, of course, so we can test $? for truth to detect a failed process, whether it exited with a non-zero status or aborted by a signal. Of course, since such codes are often left to the discretion of the developer to respect, we cannot always rely on that.

In some cases, particularly if we wrote the external command, the returned code may be an errno value, which we can assign to $! for a textual description of the error. In the parent process:

wait;
$exitcode = $? >> 8;
if ($exitcode) {
    $! = $exitcode; #assign to $! to 'recreate' error
    die "Child aborted with error: $! ";
}

If there are no child processes, then wait returns immediately with a return value of -1. However, this is not generally useful since we should not be in the position of calling wait if we did not fork first, and if we did attempt to fork, we should be testing the return value of that operation. If we are handling more than one process, we should use waitpid instead.

Handling Multiple Child Processes

If we have more than one child process, then wait is not always enough, because it will return when any child process exits. If we want to wait for a particular child, then we need to use waitpid:

$pid = fork;
if ($pid) {
   waitpid $pid, 0;
} else {
   ...child...
}

Two arguments are taken by waitpid. The first is the process ID of the child to wait for. The second argument is a flag that effects the operation of waitpid. The most common flag to place here is WNOHANG, which tells waitpid not to wait if the child is still running but return immediately with -1. This argument is one of several constants defined by the POSIX module, and we can import it either from the :sys_wait_h group or directly:

use POSIX qw(:sys_wait_h);

Or:

use POSIX qw(WNOHANG);

We can use this to periodically check for a child's exit without being forced to wait for it:

$pid = fork;
if ($pid) {
    while (waitpid $pid, WNOHANG) == −1) {
        print "Waiting for $pid... ";
        sleep 5;
    }
} else {
    ...child...
}

This works for a single child process, but if we have several children to tidy up after, we have to collect all their process IDs into a list and check all of them. This is not convenient. Fortunately, we can pass -1 to waitpid to make it behave like wait and return with the value of the first available dead child:

# wait until any child exits
waitpid −1, 0;

# this is the nonblocking version
waitpid −1, WNOHANG;

We do not necessarily want to keep checking for our children exiting, particularly if their exit status is irrelevant and we only want to remove them from the process table. What we need is a way to call waitpid when the child exits without having to check periodically in a loop. Fortunately, we can install a signal handler for the SIGCHLD signal that allows us to do exactly this. However, since more than one child could exit at once, calling waitpid only once may not be enough. An efficient signal handler thus needs to keep calling waitpid until there are no exit codes left to collect, yielding a design like this:

sub waitforchildren {
    my $pid;
    do {
        $pid = waitpid -1, WNOHANG;
    } until ($pid! == −1);
}

$SIG{CHLD} = &waitforchildren;

This is tedious, but necessary if we are to manage child processes responsibly and portably. On some systems we can get away with simply ignoring SIGCHLD and have the operating system remove dead children for us:

$SIG{CHLD} = 'IGNORE';

Or, if we can let the child change its process group, we can let init reap children instead. This is not portable across all systems, though, so in general the preceding solutions are preferred.


Note For the technically curious, Perl maps the built-in waitpid to an appropriate native function, waitpid or possibly wait4. Which is chosen depends on the platform.


POSIX Flags and Functions

The POSIX module defines several symbols and functions other than WNOHANG for use with the wait and waitpid system calls. We import all of them when we import with the :sys_wait_h tag:

use POSIX qw(:sys_wait_h);

There are actually two flags. One is WNOHANG, which we have already seen. The other, WUNTRACED, also returns process IDs for children that are currently stopped (that is, have been sent a SIGSTOP) and have not yet been resumed. For example:

$possibly_stopped_pid = waitpid -1, WNOHANG | WUNTRACED;

In addition, the convenience functions listed in Table 21-2 are defined.

Table 21-2. Convenience Functions

Function Action
WEXITSTATUS Extract the exit status if the processed has exited. Equivalent to $? >> 8. For example:
$exitcode = WEXITSTATUS($?);
The exit code is zero if the process was terminated by a signal.
WTERMSIG Extract the number of the signal that terminated the process if the process aborted on a signal. For example:
$exitsignal = WTERMSIG($?);
The signal number is zero if the process exited normally (even if with an error).
WIFEXITED Check that the process exited, as opposed to being aborted by a signal. The opposite of WIFSIGNALED. For example:
if (WIFEXITED $?) {
    return WEXITSTATUS($?)
} else {return −1};
WIFSIGNALED Check that the process terminated on a signal, as opposed to exited. The opposite of WIFEXITED. For example:
if (WIFSIGNALED $?) {
    print "Aborted on signal ",
    WTERMSIG($?), " ";
} elsif (WEXITSTATUS $?) {
    print Exited with error ",
    WEXITSTATUS($?), " ";
} else {
    # exit code was 0
    print "Success! ";
}
WSTOPSIG Extract the number of the signal that stopped the process if we specified WUNTRACED and the process returned is stopped as opposed to terminated. For example:
$stopsig = WSTOPSIG($?)
This is usually SIGSTOP, but not necessarily.
WIFSTOPPED If we specified WUNTRACED as a flag, this returns true if the returned process ID was for a stopped process:
if (WIFSTOPPED $?) {
   print "Process stopped by signal ",
   WSTOPSIG($?)," ";
} elsif (...){
...
}

Communicating Between Processes

Communicating between different processes, or interprocess communication (IPC), is a subject with many facets. Perl provides many possible ways to establish communications between processes, from simple unidirectional pipes, through bidirectional socket pairs, to fully fledged control over an externally executed command.

In this section, we are going to discuss the various ways in which different processes can communicate with one another and the drawbacks of each approach while paying particular attention to communications with an externally run command. The open function provides a simple and easy way to do this, but it can also be a dangerous one if we do not do some thorough screening. Instead we can turn to the forking version of open or use the IPC::Open2 or IPC::Open3 library modules for a safer approach.

Before covering the more advanced ways to establish communications between processes and external programs, we will cover the obvious and simple methods like system and do. They may not be sophisticated, but sometimes they are all we need to get the job done.

Very Simple Solutions

If we simply want to run an external program, we do not necessarily have to adopt measures like pipes (covered in the next section) or child processes; we can just use the system function:

system "command plus @arguments";

However, if system is passed a single argument, it checks it to see if it contains shell-special characters (like spaces, or quotes), and if present, starts a shell as a subprocess to run the command. This can be dangerous if the details of the command are supplied by the user; we can end up executing arbitrary commands like rmdir. A better approach is to pass the arguments individually, and this causes Perl to execute the command directly, bypassing the shell:

system 'command', 'plus', @arguments;

However, system only returns the exit code of the command, which is great if we want to know if it succeeded or not but useless for retrieving its output. For that, we can use the backtick operator qx or the equivalent backtick quotes:

# these two statements are identical. Note both interpolate too.
$output = `command plus @arguments`;
$output = qx/command plus @arguments/;

Unfortunately, both variants of the backtick operator create a shell, and this time there is no way to avoid it, since there is no way to pass a list of arguments. If we really want to avoid the shell, we have to start getting creative using a combination of open, pipe, and fork. Fortunately, Perl makes this a little simpler for us, as we will see shortly.

Not to be overlooked, we can also execute external programs with do if they are written in Perl. This function is essentially an enhanced version of eval that reads its input from an external file rather than having it written directly into the code. Its intended purpose is for loading in library files (other than modules, for which use or require are preferred), which do not generate output. If the script happens to print things to standard output, that will work too, so long as we don't want to control the output.

$return_value = do './local_script.pl';

The do command has a lot of disadvantages, however. Unlike eval, it does not cache the code executed for later use, and it is strictly limited in what it can do. For more useful and constructive forms of interprocess communication, we need to involve pipes.

Pipes

A pipe is, simply put, a pair of file handles joined together. In Perl, we can create pipes with the pipe function, which takes two filehandle names as arguments. One filehandle is read-only, and the other is write-only. By default, Perl attempts to buffer IO. This is also the case when we want a command to respond to each line without waiting for a series of lines to come through to flush the buffer. So we would write

pipe (READ, WRITE);
select WRITE;
$| = 1;

Or, using IO::Handle:

use IO::Handle;
pipe (READ, WRITE);
WRITE->autoflush(1);

We can also create pipes with the IO::Pipe module. This creates a "raw" IO::Pipe object that we convert into a read-only or write-only IO::Handle by calling either the reader or writer method:

use IO::Pipe;

my $pipe = new IO::Pipe;
if (fork) {
    $pipe->reader;
    # $pipe is now a read-only IO::Handle
} else {
    $pipe->writer;
    # $pipe is now a write-only IO::Handle
}

The most common use for pipes is for IPC (interprocess communication, mentioned earlier), which is why we bring them up here rather than in Chapter 12. As a quick example and also as an illustration of pipes from the filehandle perspective, here is a program that passes a message back and forth between a parent and child process using two pipes and a call to fork:

#!/usr/bin/perl
# message.pl
use warnings;
use strict;

pipe CREAD, PWRITE;   # parent->child
pipe PREAD, CWRITE;   # child->parent

my $message = "S";

if (fork) {
    # parent--close child end of pipes
    close CREAD;
    close CWRITE;

    syswrite PWRITE, "$message ";
    while (<PREAD>) {
        chomp;
        print "Parent got $_ ";
        syswrite PWRITE, "P$_ ";
        sleep 1;
    }
} else {
    # child--close parent end of pipes
    close PREAD;
    close PWRITE;

    while (<CREAD>) {
        chomp;
        print "Child got $_ ";
        syswrite CWRITE, "C$_ ";
    }
}

As this example shows, both processes have access to the filehandles of the pipes after the fork. Each process closes the two filehandles that it does not need and reads and writes from the other two. In order to ensure that buffering does not deadlock the processes waiting for each other's message, we use the system-level syswrite function to do the actual writing, which also absolves us of the need to set the autoflush flag. When run, the output of this program looks like this:


Child got : S
Parent got: CS
Child got : PCS
Parent got: CPCS
Child got : PCPCS
Parent got: CPCPCS

...

Note that this program works because each process reads exactly one line of input and produces exactly one line of output, so they balance each other. A real application where one side or the other needs to read arbitrary quantities of data will have to spend more time worrying about deadlocks; it is all too easy to have both processes waiting for input from the other.

Opening and Running External Processes

If the first or last character of a file name passed to open is a pipe (|) symbol, the remainder of the file name is taken to be an external command. A unidirectional pipe connects the external process to our program. Input to or output from the external process is connected to our process based on the position of the pipe symbol. If the symbol precedes the command, the program's input (STDIN) is connected to an output statement in our process. If the symbol appends the command, the program's output (STDOUT) is accessed with an input type statement from our process.

If the pipe character occurs at the start of the file name, then the input to the external command is connected to the output of the filehandle, so printing to the filehandle will send data to the input of the command. For example, here is a standard way of sending an e-mail on a Unix system by running the sendmail program and writing the content of the e-mail to it through the pipe:

# get e-mail details from somewhere, e.g., HTML form via CGI.pm
my ($from_addr, $to_addr, $subject, $mail_body, $from_sig) = get_email();

# open connection to 'sendmail' and print e-mail to it
open (MAIL, '|/usr/bin/sendmail -oi -t') || die "Eep! $! ";
print MAIL <<END_OF_MAIL;
From: $from_addr;
To: $to_addr
Subject: $subject

$mail_body
$from_sig
END_OF_MAIL

# close connection to sendmail
close MAIL;

If, on the other hand, the pipe character occurs at the end, then the output of the external command is connected to the input of the filehandle. Reading from the filehandle will receive anything that the external command prints. For example, here is another Unix-based example of using an open to receive the results of a ps (list processes) command:

#!/usr/bin/perl
# pid1.pl
use warnings;
use strict;

my $pid = open (PS,"ps aux|") || die "Couldn't execute 'ps': $! ";
print "Subprocess ID is: $pid ";
while (<PS>) {
    chomp;
    print "PS: $_ ";
}
close PS;

The return value of open when it is used to start an external process this way is the process ID of the executed command. We can use this value with functions such as waitpid, which we covered earlier in the chapter.

Note that it is not possible to open an external program for both reading and writing this way, since the pipe is unidirectional. Attempting to pass a pipe in at both ends will only result in the external command's output being chained to nothing, which is unlikely to be what we want. One solution to this is to have the external command write to a temporary file and then read the temporary file to see what happened:

if (open SORT, "|sort > /tmp/output$$") {
    ... print results line by line to SORT ...
    close SORT;

    open(RESULT, '/tmp/output$$')
    ... read sorted results ...
    close RESULT;

    unlink '/tmp/output$$';
}

Another, better, solution is to use the IPC::Open2 or IPC::Open3 module, which allows both read and write access to an external program. The IPC:: modules are also covered in this chapter, under the section "Bidirectional Pipes to External Processes."

Bidirectional Pipes

Standard pipes on Unix are only one-way, but we can create a pair of filehandles that look like just a pipe, but one that can flow in both directions. Perl provides a number of functions to create and manage sockets, which are bidirectional networking endpoints represented in our applications as filehandles. They can be used to communicate between different processes and different systems across a network, and a large part of Chapter 22 is concerned with them. Here, however, we are interested in their use for local interprocess communications.

The socketpair function stands apart from the other socket functions because it does not have any application in networking applications. Instead, it creates two sockets connected back to back, with the output of each connected to the input of the other. The result is what looks and feels like a bidirectional pipe. (Unfortunately, Windows programmers are out of luck here—the concept is not valid on these platforms.)

Sockets have domains, types, and protocols associated with them. The domain in Perl can be either the Internet or Unix, the type a streaming socket, datagram socket, or raw socket, and the protocol can be something like PF_INET or PF_UNIX (these constants actually stand for Protocol Families). This is the general form of socketpair being used to create a parent and child filehandle:

socketpair PARENT, CHILD, $domain, $type, $protocol;

However, most of this is fairly irrelevant to socketpair; its sockets do not talk to network interfaces or the file system, they do not need to listen for connections, they cannot be bound to addresses, and finally they are not bothered about protocols, since they have no lower-level protocol API to satisfy. Consequently, we generally use a Unix domain socket, since they are more lightweight than an Internet domain socket. We make it streaming so we can use it like an ordinary filehandle, and not bother with the protocol at all. The actual use of socketpair is thus almost always

use Socket;

socketpair PARENT, CHILD, AF_UNIX, SOCK_STREAM, PF_UNSPEC;

Here is a version of the message passing program we showed earlier using a pair of sockets rather than two pairs of pipe handles:

#!/usr/bin/perl
# socketpair.pl
use warnings;
use strict;

use Socket;

socketpair PARENT, CHILD, AF_Unix, SOCK_STREAM, PF_UNSPEC;

my $message = "S";

if (fork) {
    syswrite PARENT, "$message ";
    while (<PARENT>) {
        chomp;
        print "Parent got: $_ ";
        syswrite PARENT, "P$_ ";
        sleep 1;
    }
} else {
    while (<CHILD>) {
        chomp;
        print "Child got : $_ ";
        syswrite CHILD, "C$_ ";
    }
}

In fact, we could also close the parent and child socket handles in the child and parent processes respectively, since we do not need them—we only needed one end of each pipe. We can also use the socket in only one direction by using the shutdown function to close either the input or the output:

shutdown CHILD, 1;    # make child read-only
shutdown PARENT, 0;   # make parent write-only

The difference between close and shutdown is that close only affects the filehandle itself; the underlying socket is not affected unless the filehandle just closed was the only one pointing to it. In other words, shutdown includes the socket itself, and hence all filehandles associated with it are affected.

This program is a lot more advanced in the way that it manufactures the conduit between the two processes, because it uses Perl's socket support to create the filehandles, but the benefit is that it makes the application simpler to write and generates fewer redundant filehandles.

Avoiding Shells with the Forked Open

One problem with using open to start an external process is that if the external command contains spaces or other such characters that are significant to a shell, open will run a shell as a subprocess and pass on the command for it to interpret, so that any special characters can be correctly parsed. The problem with this is that it is potentially insecure if the program is to be run by untrusted users, and it will fail if taint mode is enabled through the -T option, as, for example, is the case with a CGI script. Functions such as exec and system allow us to separate the parameters of a command into separate scalar values and supply them as a list, avoiding the shell.

Unfortunately, open does not directly allow us to pass in a command as a list. Instead it allows us to use exec to actually run the command by supplying it with the magic file names |- or -|. This causes open to create a pipe and then fork to create a child process. The child's standard input or standard output (depending on whether |- or -| was used) is connected to the filehandle opened in the parent. If we then use exec to replace the child process with the external command, the standard input or output is inherited, connecting the external process directly to the filehandle created by open in the parent.

The return value from open in these cases is the process ID of the child process (in the parent) and zero (in the child), the same as the return value from fork, enabling us to tell which process we are now running as.

Of course, it is not obligatory to run an external command at this point, but this is by far the most common reason for using a forked open. It is also by far the most common reason for using exec, which replaces the current process by the supplied command. Since exec allows the command to be split up into a list (that is, a list containing the command and arguments as separate elements), we can avoid the shell that open would create if we used it directly (or handed it a scalar string with the complete command and arguments in it). Here's an example of running the Unix ps command via a forked open:

#!/usr/bin/perl
# pid2.pl
use warnings;
use strict;

my $pid = open (PS, "-|");
die "Couldn't fork: $! " unless defined $pid;
if ($pid) {
    print "Subprocess ID is: $pid ";
    while (<PS>) {
        chomp;
        print "PS: $_ ";
    }
    close PS;
} else {
    exec qw[ps -ef];   # no shells here
}

Or, more tersely and without recording the process ID:

#!/usr/bin/perl
# pid3.pl
use warnings;
use strict;

open (PS, "-|") || exec 'ps', '-ef';
while (<PS>) {

    chomp;
    print "PS: $_ ";
}
close PS;

Bidirectional Pipes to External Processes

Perl provides a pair of modules, IPC::Open2 and IPC::Open3, that provide access to bidirectional pipes. These modules have the added advantage that the subroutines they supply, open2 and open3, permit the external commands to be given as a list, again avoiding an external shell.

As we know from Chapter 12, all applications get three filehandles for free when they start and are represented by STDIN, STDOUT, and STDERR. These are the three filehandles all applications use, and they are also the three filehandles with which we can talk and listen to any external process. This is what the piped open does, but only for one of the filehandles. However, due to the facts that STDIN is read-only and STDOUT and STDERR are write-only, we can in theory create pipes for each of them, since we only need a unidirectional conduit for each handle. This is what the open2 and open3 subroutines provided by IPC::Open2 and IPC::Open3 do. The difference between them is that open2 creates pipes for standard input and output, whereas open3 deals with standard error too.

Using either module is very simple. In the old style of Perl IO programming, we supply typeglobs (or typeglob references) for the filehandles to associate with the external command, followed by the command itself:

use IPC::Open2;

my $pid = open2(*RD, *WR, @command_and_arguments);

Or:

use IPC::Open3;

my $pid = open3(*WR, *RD, *ERR, @command_and_arguments);

Confusingly, the input and output filehandles of open2 are in a different order in open3. This is a great source for errors, so check carefully, or only use open3 to avoid getting them the wrong way around.

Since typeglobs are considered somewhat quaint these days, we can also pass in IO::Handle objects for much the same effect:

use IPC::Open2;
use IO::Handle;

my $in = new IO::Handle;
my $out = new IO::Handle;
my $pid = open2($in, $out, 'command', 'arg1', 'arg2'),
print $out "Hello there ";
my $reply = n;

In a similar vein but without the explicit calls to IO::Handle's new method, we can have open2 or open3 create and return the filehandles for us if we pass in a scalar variable with an undefined value:

use IPC::Open3;

my ($in,$out,$error);
my $pid = open3($out, $in, $error, 'command', 'arg1', 'arg2'),
print $out "Hello there ";
my $reply = n;

Both open2 and open3 perform a fork-and-exec behind the scenes, in the same way that a forked open does. The return value is the process ID of the child that actually executed (with exec) the external command. In the event that establishing the pipes to the external command fails, both subroutines raise a SIGPIPE signal, which we must catch or ignore (this we have covered earlier on in the chapter). Neither subroutine is concerned with the well being of the actual external command, however, so if the child aborts or exits normally, we need to check for ourselves and clean up with waitpid:

use POSIX qw(WNOHANG);

my $pid = open2($in, $out, 'command', @arguments);
until (waitpid $pid, WNOHANG) {
    # do other stuff, and/or read/writes to $in & $out
}

Note that this particular scheme assumes we are using nonblocking reads and writes; otherwise, the waitpid may not get called. We can also check for a deceased external process by detecting the EOF condition on the input or error filehandles (or by returning nothing from a sysread), but we still need to use waitpid to clean up the child process.

If we do not want to do anything else in the meantime, perhaps because we have another child process busy doing things elsewhere, we can simply say

# wait for child process to finish
waitpid $pid, 0;

If the write filehandle is prefixed with >&, then the external command is connected directly to the supplied filehandle, so input that arrives on it is sent directly to the external command. The filehandle is also closed in our own process. Similarly, if <& is given to the read or error filehandles, they are connected directly to the application. Here's a script that illustrates this in action:

# Usage: myscript.pl 'somecommand @args'

use IPC::Open3;

print "Now entering $ARGV[0] ";
my $pid = open3('>&STDIN', '<&STDOUT', '<&STDERR', @ARGV);
waitpid $pid, 0;
print "$ARGV[0] finished. ";

Note that we use standard input for the writing handle and standard output for the reading handle. That's because this script is a middleman in the transaction; input comes in from standard input but then goes out to the external command, and vice versa for standard output.

With a little embellishment, this script could be made useful, for example, logging uses of various commands, checking arguments, or processing tainted data.

We do not have to redirect all three filehandles, only the ones we don't want to deal with:

sub open2likeopen3 {
    return open3(shift, shift, '>&STDERR', @_);
}

This implements a subroutine functionally identical to open2 (unless we already have redirected standard error, that is) but with the arguments in the same order as open3.

Handling Bidirectional Communications

Some external commands will communicate with us on a line-by-line basis. That is, whenever we send them something, we can expect at least one line in response. In these cases, we can alternate between writing and reading as we did with our pipe and socketpair examples earlier. Commands like ftp are a good example of this kind of application.

However, many commands can accept arbitrary input and will not send any output until they have received all of the input. The only way to tell such a command that it has all the input it needs is to close the filehandle, so we often need to do something like this:

@instructions = <ARGV>;
($in, $out);

# send input and close filehandle
$pid = open2($in, $out, 'command', @arguments);
print $out @instructions;
close $out;
# receive result
@result = n;
close $in;

# clean up and use the result
waitpid $pid, 0;
print "Got: @result";

If we want to carry out an ongoing dialog with an external process, then an alternating write-read-write process is not always the best way to approach the problem. In order to avoid deadlocks, we have to continually divert attention from one filehandle to the other. Adding standard error just makes things worse.

Fortunately, there are two simple solutions, depending on whether we can (or want to) fork or not. First, we can use the select function or the vastly more convenient IO::Select module to poll multiple input filehandles, including both the normal and error output of the external command plus our own standard input. Alternatively, we can fork child processes to handle each filehandle individually. We can even use threads, if we have a version of Perl that is built to use them. We go into more detail on threads later on.

Sharing Data Between Processes

The problem with forked processes, as we have observed before and will observe again when we get to threads, is that they do not share data easily. Consequently, to communicate with each other or share resources, processes need to either establish a channel for communication or find some common point of reference that can be seen by all the processes concerned.

In this section, we are going to discuss the IPC facilities provided by Unix systems and their near cousins, generically known as System V IPC, after the variant of Unix in which it first appeared. There are three components to System V IPC: message queues, semaphores, and shared memory segments. System V IPC is now a fairly venerable part of Unix and is not generally portable to non-Unix platforms that do not comply with POSIX. Some parts of it are also implemented through pipes and socket pairs for ease of implementation. It still has its uses, though, in particular because the objects that we can create and access with it are persistent in memory and can survive the death of the applications that use them. This allows an application to store all its mission-critical data in shared memory and to pick up exactly where it left off if it is terminated and restarted.

Like most parts of Perl that interface to a lower-level library, IPC requires a number of constants that define the various parameters required by its functions. For IPC, these constants are defined by the IPC::SysV module, so almost any application using IPC includes the statement

use IPC::SysV;

Note that we do not actually have to be on a System V Unix platform to use IPC, but we do have to be on a platform that has the required IPC support. In general, Perl will not even have the modules installed if IPC is not available, and we will have to find alternative means to our goal, some of which are illustrated during the course of the other sections in this chapter. Even on Unix systems IPC is not always present. If it is, we can usually find out by executing this command:

> ipcs

If IPC is available, this will produce a report of all currently existing shared memory segments, semaphores, and message queues, usually in that order.

The common theme between IPC message queues, semaphores, and shared memory segments is that they all reside persistently in memory and can be accessed by any process that knows the resource ID and has access privileges. This differentiates them from most other IPC strategies, which establish private lines of communication between processes that are not so easily accessed by other unrelated processes.

Strictly speaking, Perl's support for IPC is available in the language as the function calls msgctl, msgget, msgrcv, msgsnd, semctl, semget, semop, shmctl, shmget, shmread, and shmwrite. These are merely wrappers for the equivalent C calls, and hence are pretty low level, though very well documented. However, since these functions are not very easy to use, the IPC:: family of modules includes support for object-oriented IPC access. In the interests of brevity, we will concentrate on these modules only in the following sections.

IPC::SysV

The IPC::SysV module imports all of the specified SysV constants for use in our programs in conjunction with the other IPC modules. Table 21-3 presents a summary of the most widely used constants. To see the full set of what IPC::SysV can export, we can do a perldoc -m on the module and consult development man pages for further information. Error constants are imported with the core module Errno.

Table 21-3. Widely Used SysV Constants

Constant Purpose
GETALL Return an array of all the values in the semaphore set.
GETNCNT Return the number of processes waiting for an increase in value of the specified semaphore in the set.
GETPID Return the PID of the last process that performed an operation on the specified semaphore in the set.
GETVAL Return the value of the specified semaphore in the set.
GETZCNT Return the number of processes waiting for the specified semaphore in the set to become zero.
IPC_ALLOC Currently allocated.
IPC_CREAT Create entry if key doesn't exist.
IPC_EXCL Fail if key exists.
IPC_NOERROR Truncate the message and remove it from the queue if it is longer than the read buffer size (normally keeps the message, and returns an error) when applied to message queues.
IPC_NOWAIT Error if request must wait.
IPC_PRIVATE Private key.
IPC_RMID Remove resource.
IPC_SET Set resource options.
IPC_STAT Get resource options.
IPC_W Write or send permission.
MSG_NOERROR The same as IPC_NOERROR.
SEM_UNDO Specify the operation be rolled when the calling process exits.
SETALL Set the value of all the semaphores in the set to the specified value.
SETVAL Set the value of the semaphore in the set to the specified value.
S_IRUSR 00400: Owner read permission.
S_IWUSR 00200: Owner write permission.
S_IRWXU 00700: Owner read/write/execute permission.
S_IRGRP 00040: Group read permission.
S_IWGRP 00020: Group write permission.
S_IRWXG 00070: Group read/write/execute permission.
S_IROTH 00004: Other read permission.
S_IWOTH 00002: Other write permission.
S_IRWXO 00007: Other read/write/execute permission.
ftok Convert a pathname and a process ID into a key_t-type SysV IPC identifier.

Messages Queues

At one time, message queues were the only effective way to communicate between processes. They provide a simple queue that processes may write messages into at one end and read out at the other. We can create two kinds of queues, private and public. Here is an example of creating a private queue:

use IPC::SysV qw(IPC_PRIVATE IPC_CREAT S_IRWXU);
use IPC::Msg;

my $queue = new IPC::Msg IPC_PRIVATE, S_IRWXU | IPC_CREAT;

The new constructor takes two arguments. The first is the queue's identifier, which for a private queue is IPC_PRIVATE. The second is the permissions of the queue, combined with IPC_CREAT if we wish to actually create the queue. Like files, queues have a mask for user, group, and other permissions. This allows us to create a queue that we can write to, but applications running under other user IDs can only read from.

For a private queue, full user permissions are the most obvious, and we specify these with S_IRWXU. This is defined by the Fcntl module, but IPC::SysV imports the symbols for us, so we don't have to use Fcntl ourselves. We could also have said 0700 using octal notation. (Permissions are discussed in detail in Chapter 13.)

If the queue is private, only the process that created the queue and any forked children can access it. Alternatively, if it is public, any process that knows the queue's identifier can access it. For a queue to be useful, therefore, it needs to have a known identifier, or key, by which it can be found. The key is simply an integer, so we can create a public queue, which can be written to by processes running under our user ID (that is, this application) and only read by others with something like the following:

# create a queue for writing
my $queue = new IPC::Msg 10023, 0722 | IPC_CREAT;

Another process can now access this message queue with

my $queue = new IPC::Msg 10023, 0200;

On return, $queue will be a valid message object for the queue, or undef if it did not exist. Assuming success, we can now read and write the queue to establish communications between the processes. If we had created a private queue (not specifying the SysV ID key) and we want to send the message queue's key to another process so we can establish communications, we can extract it with id:

my $queue = new IPC::Msg IPC_PRIVATE, 0722 | IPC_CREAT;
my $id = $queue->id;

To send a message, we use the snd method:

$queue->snd($type, $message, $flags);

The message is simply the data we want to send. The type is a positive integer, which can be used by the rcv method to select different messages based on their type. The flags argument is optional, but it can be set to IPC_NOWAIT to have the method return if the message could not be sent immediately (in this case, $! will be set to EAGAIN). It is possible for error code constants to be imported by the module.

To receive a message, we use the rcv method:

my $message;
$queue->rcv($message, $length, $type, $flags);

The first argument must be a scalar variable into which the message is read. The second defines the maximum length of the message to be received. If the message is larger than this length, then rcv returns undef and sets $! to E2BIG. The type allows us to control which message we receive and is an integer with the following possible meanings:

Integer Value Meaning
0 Read the first message on the queue, regardless of type.
> 0 Read the first message on the queue of the specified type. For example, if the type is 2, then only messages of type 2 will be read. If none are available, this will cause the process to block until one is. However, see IPC_NOWAIT and MSG_EXCEPT later.
< 0 Read the lowest and furthest forward message on the queue with a type equal to or less than the absolute value of the specified type. For example, if the type is -2, then the first message with type 0 will be returned; if no messages of type 0 are present, the first message of type 1, or if no messages of type 1 are present, the first message of type 2 is returned.

The flags may be one or more of the following:

Flag Action
MSG_EXCEPT Invert the sense of the type so that for zero or positive values it retrieves the first message not of the specified type. For instance, a type of 1 causes rcv to return the first message not of type 1.
MSG_NOERROR Allow outsize messages to be received by truncating them to the specified length, rather than returning E2BIG as an error.
IPC_NOWAIT Do not wait for a message of the requested type if none are available but return with $! set to EAGAIN.

Put together, these two functions allow us to set up a multilevel communications queue with differently typed messages for different purposes. The meaning of the type is entirely up to us; we can use it to send different messages to different child processes or threads within our application. Also it can be used as a priority or out-of-band channel marker, to name a few some examples.

The permissions of a queue can be changed with the set method, which takes a list of key-value pairs as parameters:

$queue->set (
    uid => $user_id,        # i.e., like 'chmod' for files
    gid => $group_id,       # i.e., like 'chgrp' for files
    mode => $permissions,   # an octal value or S_ flags
    qbytes => $queue_size   # the queue's capacity
)

We can also retrieve an IPC::Msg::stat object, which we can in turn create, modify, and then update the queue properties via the stat method:

my $stat = $queue->stat;
$stat->mode(0722);
$queue->set($stat);

The object that the stat method returns is actually an object based on the Class::Struct class. It provides the following get/set methods (the * designates portions of the stat structure that cannot be directly manipulated):

Method Purpose
uid The effective UID queue is running with
gid The effective GID queue is running with
cuid* The UID queue was started with
cgid* The GID queue was started with
mode Permissions set on the queue
qnum* Number of messages currently in the queue
qbytes Size of the message queue
lspid* PID of the last process that performed a send on the queue
lrpid* PID of the last process that performed a receive on the queue
stime* Time of the last send call performed on the queue
rtime* Time of the last receive call performed on the queue
ctime* Time of the last change performed on the stat data structure

Note that changes made to the object returned by the stat method do not directly update the queue's attributes. For that to happen, we need to either pass the updated stat object or individual key-value pairs (using the keys listed previously as stat methods) to the set method.

Finally, we can destroy a queue, assuming we have execute permission for it, by calling remove:

$queue->remove;

If we cannot remove the queue, the method returns undef, with $! set to indicate the reason, most likely EPERM. In keeping with good programming practices, it is important that the queue be removed, especially since it persists even after the application exits. However, it is equally important that the correct process do so, and no other process pulls the rug out from under the others.

Semaphores

IPC semaphores are an in-memory set of numeric flags (also known as semaphore sets) that can be read and written by different processes to indicate different states. Like message queues, they can be private or public, having an identifier by which they can be accessed with a permissions mask controlling who can access them.

Semaphores have two uses: first, as a set of shared values, which can be read and written by different processes; and second, to allow processes to block and wait for semaphores to change value, so that the execution of different processes can be stopped and started according to the value of a semaphore controlled by a different process.

The module that implements access to semaphores is IPC::Semaphore, and we can use it like this:

use IPC::SysV qw(IPC_CREAT IPC_PRIVATE S_IRWXU);
use IPC::Semaphore;

my $size = 4;
my $sem = new IPC::Semaphore(IPC_PRIVATE, $size, IPC_CREAT | S_IRWXU);

This creates a private semaphore set with four semaphores and owner read, write, and execute permissions. To create a public semaphore set, we provide a literal key value instead:

my $sem = new IPC::Semaphore(10023, 4, 0722 | IPC_CREAT);

Other processes can now access the semaphore with

my $sem = new IPC::Semaphore(10023, 4, 0200);   # or S_IRDONLY

As with message queues, we can also retrieve the key of the semaphore set with the id method:

$id = $sem->id;

Once we have access to the semaphore, we can use and manipulate it in various ways, assuming we have permission to do so. A number of methods exist to help us do this, and these are listed here:

Name Action
getall Return all values as a list. For example:
my @semvals = $sem->getall;
getval Return the value of the specified semaphore. For example:
# first semaphore is 0, so 4th is 3
my $sem4 = $sem->getval(3);
setall Set all semaphore values. For example, to clear all semaphores:
$sem->setall( (0) × 4 );
setval Set the value of the specified semaphore. For example:
# set value of 4th semaphore to 1
$sem->setval(3, 1);
set Set the user ID, group ID or permissions of the semaphore, for example:
$sem->set(
   uid => $user_id,
      gid => $group_id,
   mode => $permissions,
);

Alternatively we can get, manipulate, and set a stat object as returned by the stat method in the same manner as IPC::Msg objects.

Name Action
stat Generate a IPC::Semaphore::stat object we can manipulate and then use with set. For example:
$semstat = $sem->stat;
$semstat->mode(0722);
$sem->set($semstat);
getpid Return the process ID of the last process to perform a semop operation on the semaphore set.
getncnt Return the number of processes that have executed a semop and are blocked waiting for the value of the specified semaphore to increase in value.
$ncnt = $sem->getncnt;
getzcnt Return the number of processes that have executed a semop and are blocked waiting for the value of the specified semaphore to become zero.

The real power of semaphores is bound up in the op method, which performs one or more semaphore operations on a semaphore set. This is the mechanism by which processes can block and be unblocked by other processes.

Each operation consists of three values: the semaphore number to operate on, an operation to perform, and a flag value. The operation is actually a value to increment or decrement by, and it follows these rules:

  • If the value is positive, the semaphore value is incremented by the supplied value. This always succeeds, and never blocks.
  • If the supplied value is zero, and the semaphore value is zero, the operation succeeds. If the semaphore value is not zero, then the operation blocks until the semaphore value becomes zero. This increases the value returned by getzcnt.
  • If the value is negative, then the semaphore value is decremented by this value, unless this would take the value of the semaphore negative. In this case, the operation blocks until the semaphore becomes sufficiently positive enough to allow the decrement to happen. This increases the value returned by getncnt.

We can choose to operate as many semaphores as we like. All operations must be able to complete before the operation as a whole can succeed. For example:

$sem->op(
   0, −1, 0,   # decrement semaphore 1
   1, −1, 0,   # decrement semaphore 2
   3,  0, 0,   # semaphore 3 must be zero
);

The rules for blocking on semaphores allow us to create applications that can cooperate with each other; one application can control the execution of another by setting semaphore values. Applications can also coordinate over access to shared resources. This a potentially large subject, so we will just give an simple illustrative example of how a semaphore can coordinate access to a common shared resource:

  1. Application 1 creates a semaphore set with one semaphore, value 1, and creates a shared resource, for example, a file or an IPC shared memory segment. However, it decides to do a lot of initialization, and so it doesn't access the resource immediately.
  2. Application 2 starts up, decrements the semaphore to 0, and accesses the shared resource.
  3. Application 1 now tries to decrement the semaphore and access the resource. The semaphore is 0, so it cannot access it and therefore blocks.
  4. Application 2 finishes with the shared resource and increments the semaphore, an operation that always succeeds.
  5. Application 1 can now decrement the semaphore since it is now 1, and so the operation succeeds and no longer blocks.
  6. Application 2 tries to access the resource a second time. First it tries to decrement the semaphore, but is unable to, and blocks.
  7. Application 1 finishes and increments the semaphore.
  8. Application 2 decrements the semaphore and accesses the resource.

And so on . . .

Although this sounds complex, in reality it is very simple. In code, each application simply accesses the semaphore, creating it if not present, then adds two lines around all accesses to the resource to be protected:

sub access_resource {
    # decrement semaphore, blocking if it is already zero
    $sem->op(0, −1, 0);
    ... access resource ...
    # increment semaphore, allowing access by other processes
    $sem->op(0, 1, 0);
}

If we have more than one resource to control, we just create a semaphore set with more semaphores.

The basis of this approach is that the applications agree to cooperate through the semaphore. Each one has the key for the semaphore (because it is given in a configuration file, for instance), and it becomes the sole basis for contact between them. Even though the resource being controlled has no direct connection to the semaphore, each application always honors it before accessing it. The semaphore becomes a gatekeeper, allowing only one application access at a time.

If we do not want to block while waiting for a semaphore, we can specify IPC_NOWAIT for the flag value. We can do this on a "per semaphore basis" too, if we want, though this could be confusing. For example:

sub access_resource {
    return undef unless $sem->op(0, −1, IPC_NOWAIT);
    ... access resource ...
    $sem->op(0, 1, 0);
}

We can also set the flag SEM_UNDO (if we import it from IPC::SysV first). This causes a semaphore operation to be automatically undone if the process exits, either deliberately or due to an error. This is helpful in preventing applications that abort while locking a resource and then never releasing it again. For example:

$sem->op(0, −1, IPC_NOWAIT | SEM_UNDO);
die unless critical_subroutine();

As with message queues, care must be given to not leave unused segments around after the last process exits.

We will return to the subject of semaphores when we come to talk about threads, which have their own semaphore mechanism, inspired greatly by the original IPC implementation described previously.

Shared Memory Segments

While message queues and semaphores are relatively low-level constructs made a little more accessible by the IPC::Msg and IPC::Semaphore modules, shared memory has altogether more powerful support module in the form of IPC::Shareable. The key reason for this is that IPC::Shareable implements shared memory through a tie mechanism, so rather than reading and writing from a memory block, we can simply attach a variable to it and use that.

The tie takes four arguments, a variable (which may be a scalar, an array, or a hash), IPC::Shareable for the binding, and then an access key, followed optionally by a hash reference containing one or more key-value pairs. For example, the following code creates and ties a hash variable to a shared memory segment:

use IPC::Shareable;

our %local_hash;
tie %local_hash, 'IPC::Shareable', 'key', {create => 1}

$local_hash{hashkey} = 'value';

This creates a persistent shared memory object containing a hash variable that can be accessed by any application or process by tie-ing a hash variable to the access key for the shared memory segment (in this case key):

# in a process in an application far, far away...
%other_hash;
tie %other_hash, IPC::Shareable => 'key';

$value = $other_hash{hashkey};

A key feature of shared memory is that, like memory queues and semaphores, the shared memory segment exists independently of the application that created it. Even if all the users of the shared memory exit, it will continue to exist so long as it is not explicitly deleted (we can alter this behavior, though, as we will see in a moment).

Note that the key value is actually implemented as an integer, the same as semaphores and message queues, so the string we pass is converted into an integer value by packing the first four characters into a 32-bit integer value. This means that only the first four characters of the key are used. As a simple example, baby and babyface are the same key to IPC::Shareable.

The tied variable can be of any type, including a scalar containing a reference, in which case whatever the reference points to gets converted into a shared form. This includes nested data structures and objects, making shared memory ties potentially very powerful. However, each reference becomes a new shared memory object, so a complex structure can quickly exceed the system limit on shared memory segments. In practice, we should only try to tie relatively small nested structures to avoid trouble.

The fourth argument can contain a number of different configuration options that determine how the shared memory segment is accessed, as listed in Table 21-4.

Table 21-4. IPC::Shareable Configuration Options

Option Function
create If true, create the key if it does not already exist. If the key does exist, then the tie succeeds and binds to the existing data, unless exclusive is also true. If create is false or not given, then the tie will fail if the key is not present.
exclusive Used in conjunction with create. If true, allow a new key to be created but do not allow an existing key to be tied to successfully.
mode Determine the access permissions of the shared memory segment. The value is an integer, traditionally an octal number or a combination of flags like S_IRWXU | S_IRGRP.
destroy If true, cause the shared memory segment to be destroyed automatically when this process exits (but not if it aborts on a signal). In general, only the creating application should do this or be able to do this (by setting the permissions appropriately on creation).
size Define the size of the shared memory segment, in bytes. In general, this defaults to an internally set maximum value, so we rarely need to use it.
key If the tie is given three arguments, with the reference to the configuration options being the third, this value specifies the name of the share memory segment:
tie %hash, 'IPC::Shareable' {key => 'key', ...}; For example:
tie @array, 'IPC::Shareable', 'mysharedmem', {
   create => 1,
   exclusive => 0,
   mode => 722,
   destroy => 1,
}

Other than the destroy option, we can remove a shared memory segment by calling one of three methods implemented for the IPC::Shareable object that implements the tie (which may be returned by the tied function), as shown in Table 21-5.

Table 21-5. IPC::Shareable Methods

Method Purpose
remove Remove the shared memory segment, if we have permission to do so.
clean_up Remove all shared memory segments created by this process.    
clean_up_all Remove all shared memory segments in existence for which this process has permissions to do so.
For example:
# grab a handle to the tied object via the 'tied'
# command
$shmem = tied $shared_scalar;
# use the object handle to call the 'remove' method on
# it
print "Removed shared scalar" if $shmem->remove;

We can also lock variables using the IPC::Shareable object's shlock and shunlock methods. If the variable is already locked, the process attempting the lock will block until it becomes free. For example:

$shmem->lock;
$shared_scalar = "new value";
$shmem->unlock;

Behind the scenes this lock is implemented with IPC::Semaphore, so for a more flexible mechanism, use IPC::Semaphore objects directly.

As a lightweight alternative to IPC::Shareable, we can make use of the IPC::ShareLite module, naturally available from CPAN. This provides a simple store-fetch mechanism using object methods and does not provide a tied interface. However, it is faster than IPC::Shareable.

Threads

Threads are, very loosely speaking, the low fat and lean version of forked processes. Like processes, each thread is a separate strand of execution. Also like processes, newly created threads are owned by the parent thread that created them. They also have unique identifiers, though these are thread IDs rather than process IDs. We can even wait for a thread to finish and collect its exit result, just like waitpid does for child processes.

However, threads run within the same process and share the same interpreter, code, and data. Nothing is duplicated except the thread of execution. This makes them much more lightweight, so we can have very many of them, and we don't need to use any of the workarounds that forked processes need.

Thread support for Unix platforms is still considered experimental, but as of Perl 5.8 it is increasingly robust. Windows versions of Perl are implicitly capable of threads, and in fact fork is implemented with threads on that platform—the process ID returned by fork is actually a thread ID. With a few caveats, there is no reason we cannot now write threaded Perl applications, so long as we built Perl with thread support initially, of course.

Checking for Thread Support

To find out if threads are available programmatically, we can check for the usethreads key in the %Config hash:

BEGIN {
    use Config;
    die "Threadbare! " unless $Config{usethreads};
}

This tells us threads are supported, but not which kind. If we need to check that we have interpreter threads rather than the older 5.005 threads, we can also (or instead) check for useithreads:

BEGIN {
    use Config;
    die "No interpreter threads! " unless $Config{useithreads};
}

From the command line, we can check if threads are present by trying to read the documentation. The Thread module is present for both types of thread. The threads module will only be present if interpreter thread support is enabled:

> perldoc threads

The threads module is the basis of handling threads in Perl. It is an object-oriented module that represents threads as objects, which we can create using new and manipulate with methods. In addition, it provides a number of functions that operate on a per-thread basis. The older Thread module exists even with interpreter threads as a portability aid for programs written to the old interface. However, since data is automatically shared in the older implementation and automatically kept private with interpreter threads, this gesture is unlikely to work for threaded programs of any complexity.

Thread modules come in two flavors, pragmatic and application oriented. Basic support for threads is supplied by the pragmatic threads and threads::shared modules, the latter of which provides the ability to share data between threads. These two modules interface directly into the interpreter's thread mechanics and are necessary to enable threads and shared data in our application. Although they are pragmatic, both modules also provide methods and subroutines for stating, stopping, querying, and manipulating threads.

Application-oriented thread modules live in the Thread:: namespace. The Thread::Semaphore and Thread::Queue modules, which both come standard with Perl (and which are covered later in the chapter) are two good examples, but there are plenty more interesting examples on CPAN for the curious.

Creating Threads

Threads resemble forked processes in many ways, but in terms of creation they resemble, and indeed are, subroutines. The standard way of creating a thread, the create method, takes a subroutine reference and a list of arguments to pass to it. The subroutine is then executed by a new thread of execution, while the parent thread receives a thread object as the return value. The following code snippet illustrates how it works:

use threads;

sub threadsub {
    my $self = threads->self;
    ...
}

my $thread = threads->create(&threadsub, @args);

The new method is an alias, so we can also say

my $thread = new threads(&threadsub, @args);

This creates a new thread, with threadsub as its entry point, while the main thread continues on. The alternative way to create a thread is with the async function, whose syntax is analogous to an anonymous subroutine. This function is not imported by default, so we must name it in the import list to the Thread module:

my $thread = async {
    my $self = threads->self;
    ...
};

Just like an anonymous subroutine, we end the async statement with a semicolon. The block may not need it, but the statement does.

The choice of create/new or async depends on the nature of the thread we want to start; the two approaches are identical in all respects apart from their syntax. If we only want to start one instance of a thread, then async should be used. Otherwise, create or new is better if we want to use the same subroutine for many different threads:

my $thread1 = new threads &threadsub, $arg1;
my $thread2 = new threads &threadsub, $arg2;
my $thread3 = new threads &threadsub, $arg3;

or, with a loop:

# start a new thread for each argument passed in @ARGV:
@threads;
foreach (@ARGV) {
    push @threads, threads->create(&threadsub, $_);
}

Because interpreter threads make a copy of the data in the original thread to create the new thread, we do not normally need to take any special action to create new threads, and code that is not thread-aware is automatically thread-safe. However, if we have any non-Perl data in a thread, Perl cannot deal with it directly—this particularly affects extension modules with XSUBs—and we may have a problem. To solve it, we can make use of the special CLONE method in any package that needs to deal with special cases:

package Special::Thread::Module;

sub CLONE {
    # handle any special thread cloning needs for this package
}

If present, this method is called—in every loaded package that defines or inherits it—just after the thread is created and just before its entry point is called. We can also use this method to adjust or "thin down" data that we do not need to have cloned to conserve memory.

Identifying Threads

Since we can start up many different threads all with the same subroutine as their entry point, it might seem tricky to tell them apart. However, this is not so.

First, we can pass in different arguments when we start each thread to set them on different tasks. An example of this would be a filehandle, newly created by a server application, and this is exactly what the example of a threaded server in Chapter 22 does. Second, a thread can create a thread object to represent itself using the self class method:

my $self = threads->self;

With this thread object, the thread can now call methods on itself, for example tid, which returns the underlying thread number:

my $self_id = $self->tid;

or all in one statement:

my $self_id = threads->self->tid;

It is possible to have more than one thread object containing the same thread ID, and this is actually common in some circumstances. We can check for equivalence by comparing the IDs, but we can do better by using the equals method:

print "Equal! " if $self->equal($thread);

or, equivalently:

print "Equal! " if $thread->equal($self);

Thread identities are useful for many purposes, one of the most useful being thread-specific data.

Sharing Data Between Threads

There is one major difference between the older implementation of threads provided in Perl 5.6 and earlier and the interpreter threads available in Perl 5.8 onward: data is automatically shared in the older model, and never shared, unless we ask for it, in the newer one. The older model mirrors the behavior of the underlying thread support provided by the operating system, but there is no reason for Perl to mimic this behavior in its own threads, so instead the interpreter tracks the use of data by threads and duplicates unshared data as needed. This is actually more convenient, at least for code that was not written with threads in mind, since it means that by default threads can never inadvertently interfere with each other by overwriting each other's data.

To actually share data, we make use of the threads::shared module, which provides the share function to mark a variable as shared across all threads. In actuality, this simply switches off the smart duplication of data that the interpreter would ordinarily carry out, for indicated variables only. If the threads module has not been loaded previously, share and other functions like lock and cond_wait that are also provided by this module are exported as nonfunctional stubs. This means our code will still run in a nonthreaded context, but it also means we must make sure to load threads first:

use threads;
use threads::shared;

Once a variable is shared, each thread will see the same underlying storage when the variable is accessed, rather than getting its own copy:

my $answer = 42;
share($answer);
my @array = (1,2,3);
share(@array);

If we know in advance which variables we want to share, which is generally the case, we can use the shared attribute instead:

my $answer : shared = 42;
my @array : shared = qw(1 2 3);
my %hash : shared = (one => 1, two => 2, three => 3);

We are not limited to sharing declared variables. We can also create a new anonymous reference and share it all in one go. However, since the subroutine normally expects a variable argument, we must call it with & to suppress the prototype:

my $aref = &share([1 2 3]);

Either way, once a variable is shared, all threads have access to the same data. In order to prevent them from overwriting each other and coordinate access to the shared data, we now need to apply a lock so that only one thread can access it at any given moment.

Variable Locks

When multiple threads share data, we sometimes have problems stopping them from treading on each other's toes. Since data is not shared between threads by default, we can largely ignore this problem for code that does not choose to share data, but the problem still exists when sharing common resources among a pool of threads.

The lock subroutine does handle this, however. It takes any variable as an argument and places a lock on it so that no other thread may lock it for as long as the lock persists, which is defined by its lexical scope. The distinction between lock and access is important; any thread can simply access the variable by not bothering to acquire the lock, so the lock is only good if all threads abide by it. Just like flock for filehandles, a thread variable lock is advisory, not compelled.

It is not necessarily given that because data is shared it needs to be locked. Any number of threads can read the same data without risk of conflict, after all. It is important to place a lock on the data for code that writes or modifies it, but it is not always necessary to place a lock for code that only reads it. If we write our code so that only one thread can ever update the shared data, we may not need a lock at all.

If we have three shared variables, all of which are involved in any transaction, we can lock just one of them to control access to all three or invent a new lock variable solely for the purpose—it does not matter what approach we use, so long as we do it consistently.

As a short and incomplete example, this subroutine locks a filehandle used for output, so that only one thread can write to the filehandle at a time:

my $sharedfh : shared = IO::File->open("> app.log");

sub writelog {
    lock $sharedfh;
    print $sharedfh, @_;
}

The shared and locked properties of a variable are distinct from its value, so it does not matter what (or when) we assign to the variable, or even whether we assign to it at all.

It is not necessary to explicitly unlock the variable, and in fact not possible either. The lock is released as soon as it goes out of scope, which in this case is at the end of the subroutine. Any lexical scope is acceptable, however, so we can also place locks inside the clauses of if statements, loops, map and grep blocks, and eval statements. We can also choose to lock arrays, hashes, or globs:

lock @array;
lock %hash;
lock *glob;

Alternatively, we can lock just an element, which gives us a form of record-based locking, if we define a record as an array element or hash value:

my %ghash : shared;

sub varlocksub {
    my $key = shift;
    lock $ghash{$key};
    ...
}

In this version, only one element of the hash is locked, so any other thread can enter the subroutine with a different key and the corresponding value at the same time. If a thread comes in with the same key, however, it will find the value under lock and key (so to speak) and will have to wait.

While it is possible and perfectly legal to place a lock on a hash or array, locking a hash does not imply a lock on any of its keys, and locking an array does not imply locking any of its elements. Similarly, locking a key or element does not imply a lock on the hash or array to which it belongs.

Subroutine Locks

In Perl 5.6, the locked and method attributes provided serialized access to a subroutine. Neither of these attributes exist for interpreter threads, and we can no longer lock a subroutine by reference, either. But we can lock a variable associated with the subroutine, for example, the code reference of an anonymous subroutine:

my $subref : shared = sub {
    lock $subref;
    print "This is thread ",threads->self->tid," ";
}

This is just syntactic sugar: it doesn't really matter what the variable is, so long as we relate it somehow to the subroutine to lock. We can equally use a closure, like in this example:

#!/usr/bin/perl -w
# locksub.pl
use strict;
use warnings;
use threads;
use threads::shared;

{ my $lock : shared;
  sub mysub {
      print "Thread ",threads->self->tid()," waiting for access ";
      lock $lock;
      print "I am thread ",threads->self->tid()," ";
      sleep 1;
      threads->detach();

    }
}

foreach (1..5) {
    threads->create(&mysub);
}

do {
    sleep 1;
    print "Waiting for threads:",(map { " ".$_->tid } threads->list)," ";
} while (threads->list);

The closure hides the lock variable where external code cannot get to it. Here each thread tries to execute the mysub subroutine, but only one thread can hold the lock on the closure variable $lock at any given time, and so access to the subroutine is serialized. Each thread sleeps for a second and then detaches itself to let the main thread know it is done. Meanwhile, the main thread waits for all the child threads to detach before exiting. This is a simplistic thread management scenario, of course—semaphores and queues are more sophisticated techniques we will look at in a moment.

It is not usually necessary to lock object methods this way because object instances are generally created on a per-thread basis and are not shared between threads—if we need to coordinate method access to other shared variables, then we would lock on those variables in any case. There are currently limitations on the sharing of blessed object references, so it is often inadvisable to share them in any case—see the threads::shared manual page for details. (In our IO::File example earlier, we were safe because the lock works even if the blessed nature of the glob reference is lost between threads—no IO::File methods got called.)

Thread Management

Perl keeps a list of every thread that has been created. We can get a copy of this list, as thread objects, with the threads->list class method:

@threads = threads->list;

One of these threads is our own thread. We can find out which by using the equal method:

$self = threads->self;
foreach (@threads) {
    next if $self->equal($_);
    ...
}

Just because a thread is present does not mean that it is running, however. Perl keeps a record of the return value of every thread when it exits and a record of the thread for as long as that value remains unclaimed. This is similar to child processes that have not had waitpid called for them. The threaded equivalent of waitpid is the join method, which we call on the thread we want to retrieve the exit value for:

my $return_result = $thread->join;

The join method will block until the thread on which join was called exits. If the thread aborted (for example by calling die), then the error will be propagated to the thread that called join. This means that it will itself die unless the join is protected by an eval:

my $return_result = eval { $thread->join; }
if ($@) {
    warn "Thread unraveled before completion ";
}

As a convenience for this common construct, the Thread module also provides an eval method, which wraps join inside an eval for us:

my $return_result = $thread->eval;
if ($@) {
    warn "Thread unraveled before completion ";
}

It is bad form to ignore the return value of a thread, since it clutters up the thread list with dead threads. If we do not care about the return value, then we can tell the thread that we do not want it to linger and preserve its return value by telling it to detach:

$thread->detach;

This is the thread equivalent of putting a child process in its own process group—the parent no longer gets the exit status when the child exits. The catch is that if the thread dies, nobody will notice, unless a signal handler for the __DIE__ hook has been registered and it checks threads->self for the dying thread. If we join a moribund thread from the main thread without precautions, we do have to worry about the application dying as a whole.

As a slightly fuller and more complete (although admittedly not particularly useful) example, this short program starts up five threads, then joins each of them in turn before exiting:

#!/usr/bin/perl
# join.pl
use warnings;
use strict;
# check we have threads
BEGIN {
    use Config;
    die "No interpreter threads! " unless $Config{useithreads};
}
use threads;

# define a subroutine for threads to execute
sub threadsub {
    my $self = threads->self;
    print "Thread ", $self->tid, " started ";
    sleep 10;
    print "Thread ", $self->tid, " ending ";
}

# start up five threads, one second intervals
my @threads;
foreach (1..5) {
    push @threads, new threads &threadsub;
    sleep 1;
}

# wait for the last thread started to end
while (my $thread = shift @threads) {
    print "Waiting for thread ", $thread -> tid, " to end... ";
    $thread->join;
    print "Ended ";
}

# exit
print "All threads done ";

Typically, we care about the return value, and hence would always check them. However, in this case we are simply using join to avoid terminating the main thread prematurely.

Condition Variables, Semaphores, and Queues

Locked variables have more applications than simply controlling access. We can also use them as conditional blocks by having threads wait on a variable until it is signaled to proceed. In this mode the variable, termed a condition variable, takes on the role of a starting line; each thread lines up on the block (so to speak) until the starting pistol is fired by another thread. Depending on the type of signal we send, either a single thread is given the go-ahead to continue, or all threads are signaled.

Condition variables are a powerful tool for organizing threads, allowing us to control the flow of data through a threaded application and preventing threads from accessing shared data in an unsynchronized manner. They are also the basis for other kinds of thread interaction. We can use thread semaphores, provided by the Thread::Semaphore module, to signal between threads. We can also implement a queue of tasks between threads using the Thread::Queue module. Both these modules build upon the basic features of condition variables to provide their functionality but wrap them in a more convenient form.

To get a feel for how each of these work, we will implement a basic but functional threaded application, first using condition variables directly, then using semaphores, and finally using a queue.

Condition Variables

Continuing the analogy of the starting line, to "line up" threads on a locked variable we use the cond_wait subroutine. This takes a locked variable as an argument, unlocks it, and then waits until it receives a signal from another thread. When it receives a signal, the thread resumes execution and relocks the variable.

To have several threads all waiting on the same variable, we need only have each thread lock and then cond_wait the variable in turn. Since the lock prevents more than one thread executing cond_wait at the same time, the process is automatically handled for us. The following code extract shows the basic technique applied to a pool of threads:

my $lockvar;   # lock variable - note it is not locked at this point

sub my_waiting_thread {
    # wait for signal
    {
        lock $lockvar;
        cond_wait $lockvar;
    }

    # ...the rest of the thread, where the work is done
}

for (1..10) {
    threads->create(&my_waiting_thread);
}

This code snippet shows ten threads, all of which use the same subroutine as their entry point. Each one locks and then waits on the variable $lockvar until it receives a signal. Since we don't want to retain the lock on the variable after we leave cond_wait, we place both lock and cond_wait inside their own block to limit the scope of the lock. This is important since other threads cannot enter the waiting state while we have a lock on the variable; sometimes that is what we want, but more often it isn't.

Having established a pool of waiting threads, we need to send a signal to wake one of them up, which we do with cond_signal:

# wake up one thread
cond_signal $lockvar;

This will unlock one thread waiting on the condition variable. The thread that is restarted is essentially random; we cannot assume that the first thread to block will be the first to be unlocked again. This is appropriate when we have a pool of threads at our disposal, all of which perform the same basic function. Alternatively, we can unlock all threads at once by calling cond_broadcast thusly:

# everybody up!
cond_broadcast $lockvar;

This sends a message to each thread waiting on that variable, which is appropriate for circumstances where a common resource is conditionally available and we want to stop or start all threads, depending on whether they are available or not. It is important to realize, however, that if no threads are waiting on the variable, the signal is discarded; it is not kept until a thread is ready to respond to it. It is also important to realize that this has nothing (directly) to do with process signals, as handled by the %SIG array; writing a threaded application to handle process signals is a more complex task (see the Thread::Signal module for details).

Note that the actual value of the lock variable is entirely irrelevant to this process, so we can use it for other things. For instance, we can use it to pass a value to the thread at the moment that we signal it. The following short threaded application does just this, using a pool of service threads to handle lines of input passed to them by the main thread. While examining it, pay close attention to the two condition variables that lay at the heart of the application:

  • $pool: Used by the main thread to signal that a new line is ready. It is waited on by all the service threads. Its value is programmed to hold the number of threads currently waiting, so the main thread knows whether or not it can send a signal or if it must wait for a service thread to become ready.
  • $line: Used by whichever thread is woken by the signal to $pool. Lets the main thread know that the line of input read by the main thread has been copied to the service thread and that a new line may now be read. The value is the text of the line that was read.

The two condition variables allow the main thread and the pool of service threads to cooperate with each other. This ensures that each line read by the main thread is passed to one service thread both quickly and safely:

#!/usr/bin/perl
# threadpool.pl
use warnings;
use strict;

use threads;
use threads::shared;

my $threads = 3; # number of service threads to create
my $line : shared= "";
                 # parent lock variable and input line set to "" here, we
                 # assign each new line of input to it, and set it to 'undef'
                 # when we are finished to tell service threads to quit
my $pool : shared = 0;
                 # child lock variable and pool counter set to 0 here,
                 # service threads increment it when they are ready for input

# a locked print subroutine--stops thread output mingling
{
  my $lock : shared;
  sub thr_print {
      lock $lock;
      print @_;
  }
}

# create a pool of three service threads
foreach (1..$threads) {
    threads->create(&process_thing);
}

# main loop: Read a line, wait for a service thread to become available,
# signal that a new line is ready, then wait for whichever thread picked
# up the line to signal to continue
while ($line = <>) {
    chomp $line;
    thr_print "Main thread got '$line' ";

    # do not signal until at least one thread is ready
    if ($pool==0) {
        thr_print "Main thread has no service threads available, yielding ";
        threads->yield until $pool>0;
    }
    thr_print "Main thread has $pool service threads available ";

    # signal that a new line is ready
    {
        lock $pool;
        cond_signal $pool;
    }
    thr_print "Main thread sent signal, waiting to be signaled ";
    # wait for whichever thread wakes up to signal us
    {
        lock $line;
        cond_wait $line;
    }
    thr_print "Main thread received signal, reading next line ";
}

thr_print "All lines processed, sending end signal ";
# set the line to special value 'undef' to indicate end of input
$line = undef;
{
    lock $pool;
    # tell all threads to pick up this 'line' so they all quit
    cond_broadcast $pool;
}
thr_print "Main thread ended ";
exit 0;

# the thread subroutine--block on lock variable until work arrives
sub process_thing {
    my $self=threads->self;
    my $thread_line;

    thr_print "Thread ",$self->tid," started ";
    while (1) {
        # has the 'quit' signal been sent while we were busy?
        last unless (defined $line);

        # wait to be woken up
        thr_print "Thread ",$self->tid," waiting ";
        {
            lock $pool;
            $pool++;
            cond_wait $pool; #all threads wait here for signal
            $pool--;
        }

        # retrieve value to process
        thr_print "Thread ",$self->tid," signaled ";
        $thread_line = $line;

        # was this the 'quit' signal? Check the value sent
        last unless (defined $thread_line);

        # let main thread know we have got the value
        thr_print "Thread ",$self->tid," retrieved data, signaling main ";
        {
            lock $line;
            cond_signal $line;
        }

        # do private spurious things to it
        chomp ($thread_line=uc($thread_line));
        thr_print "Thread ",$self->tid," got '$thread_line' ";
    }
    thr_print "Thread ",$self->tid," ended ";
}

Once the basic idea of a condition variable is understood, the way in which this application works becomes clearer. However, there are a few aspects still worth pointing out. In particular, the $pool variable is used by the main thread to ensure that it only sends a signal when there is a service thread waiting to receive it. To achieve this, we increment $pool immediately before cond_wait and decrement it immediately afterwards. By doing this, we ensure that $pool accurately reflects the number of waiting service threads; if it is zero, the main thread uses yield to pass on execution until a service thread becomes available again.

The means by which the application terminates is also worth noting. Threads do not necessarily terminate just because the main thread does, so in order to exit a threaded application cleanly, we need to make sure all the service threads terminate, too. This is especially important if resources needed by some threads are being used by others. In this application, the main thread uses cond_signal to signal the $pool variable and wake up one service thread when a new line is available. Once all input has been read, we need to shut down all the service threads, which means getting their entire attention. To do that, we give $line the special value undef and then use cond_broadcast to signal all threads to pick up the new "line" and exit when they see that it is undef. However, this alone is not enough because a thread might be busy and not waiting. To deal with that possibility, the service thread subroutine also checks the value of $line at the top of the loop, just in case the thread missed the signal.

Finally, this application also illustrates the use of the locked subroutine attribute. The thr_print subroutine is a wrapper for the regular print function that only allows one thread to print at a time. This prevents the output of different threads from getting intermingled. For simple tasks like this one, locked subroutines are an acceptable solution to an otherwise tricky problem that would require at least a lock variable. For longer tasks, locked subroutines can be a serious bottleneck, affecting the performance of a threaded application, so we should use them with care and never for anything likely to take appreciable time.

As of Perl 5.8.3, cond_wait can take two shared variable arguments; the first is the signal variable, the second the lock variable:

cond_wait $sigvar,$lockvar;

It works identically to the one-argument form, except for the division of responsibility. The objective is to allow us to signal the same variable several times and unlock more than one thread concurrently, by having different threads use different lock variables for the same signal variable. The number of different lock variables in play is equal to the total number of concurrent threads the signal variable can trigger.

Also from Perl 5.8.3 onwards, the threads module also provides the cond_timedwait function. It works identically to its untimed counterpart earlier, but it takes an additional timeout value in seconds. The return value of cond_timedwait is true if a signal was received and false if the timeout was reached first. This lets us write code that can periodically stop waiting to do other tasks:

{
    lock $line;
    while (! cond_timedwait($line,10)) {
        thr_print "Yawn... ";
    }
}

As with cond_wait, we can split the signal and lock variables if we wish:

cond_timedwait $sigvar,$lockvar,$timeout;

This works identically to the two-argument form, except for the division of responsibility. As with cond_wait, this form of the function allows us to signal the same variable several times and unlock more than one thread concurrently.

Semaphores

Although it works perfectly well, the preceding application is a little more complex than it needs to be. Most forms of threads whatever language or platform they reside on support the concept of semaphores, and Perl is no different. We covered IPC semaphores earlier, and thread semaphores are very similar. They are essentially numeric flags that take a value of zero or any positive number and obey the following simple rules:

  • Only one thread may manipulate the value of a semaphore in either direction at a time.
  • Any thread may increment a semaphore immediately.
  • Any thread may decrement a semaphore immediately if the decrement will not take it below zero.
  • If a thread attempts to decrement a semaphore below zero, it will block until another thread raises the semaphore high enough.

Perl provides thread semaphores through the Thread::Semaphore module, which implements semaphores in terms of condition variables—the code of Thread::Semaphore is actually quite short as well as instructive. It provides one class method, new, and two object methods, up and down. new creates a new semaphore:

$semaphore = new Thread::Semaphore;    # create semaphore, initial value 1
$semaphore2 = new Thread::Semaphore(0) # create semaphore, initial value 0

up increments a semaphore:

$semaphore->up;      # increment semaphore by 1
$semaphore->up(5);   # increment semaphore by 5

Finally, down decrements a semaphore, blocking if necessary:

$semaphore->down;    # decrement semaphore by 1
$semaphore->down(5); # decrement semaphore by 5

Depending on our requirements, we can use semaphores as binary stop/go toggles or allow them to range to larger values to indicate the availability of a resource. Here is an adapted form of our earlier threaded application, rewritten to replace the condition variables with semaphores:

#!/usr/bin/perl
# semaphore.pl
use warnings;
use strict;

use threads;
use Thread::Semaphore;

my $threads = 3;        # number of service threads to create
my $line : shared = ""; # input line

my $main = new Thread::Semaphore;    # proceed semaphore, initial value 1
my $next = new Thread::Semaphore(0); # new line semaphore, initial value 0

# a locked print subroutine--stops thread output mingling
{ my $lock : shared;
  sub thr_print {
      lock $lock;
      print @_;
  }
}

# create a pool of three service threads
foreach (1..$threads) {
    threads->create(&process_thing);
}

# main loop: read a line, raise 'next' semaphore to indicate a line is
# available, then wait for whichever thread lowered the 'next' semaphore
# to raise the 'main' semaphore, indicating we can continue.
while ($line = <>) {
    chomp $line;
    thr_print "Main thread got '$line' ";

    # notify service threads that a new line is ready
    $next->up;
    thr_print "Main thread set new line semaphore, waiting to proceed ";

    # do not proceed until value has been retrieved by responding thread
    $main->down;
    thr_print "Main thread received instruction to proceed ";
}

thr_print "All lines processed, sending end signal ";

# set the line to special value 'undef' to indicate end of input
$line = undef;
# to terminate all threads, raise 'new line' semaphore to >= number of
# service threads: all service threads will decrement it and read the
# 'undef'
$next->up($threads);
thr_print "Main thread ended ";
exit 0;

# the thread subroutine--block on lock variable until work arrives
sub process_thing {
    my $self = threads->self;
    my $thread_line;

    thr_print "Thread ", $self->tid, " started ";
    while (1) {
        # try to decrement 'next' semaphore--winning thread gets line
        thr_print "Thread ", $self->tid, " waiting ";
        $next->down;

        # retrieve value to process
        thr_print "Thread ", $self->tid, " signalled ";
        $thread_line = $line;

        # was this the 'quit' signal? Check the value sent
        last unless (defined $thread_line);

        # let main thread know we have got the value
        thr_print "Thread ", $self->tid, " retrieved data, signaling main ";
        $main->up;

        # do private spurious things to it
        chomp ($thread_line=uc($thread_line));
        thr_print "Thread ", $self->tid, " got '$thread_line' ";
    }
    thr_print "Thread ", $self->tid, " ended ";
}

The semaphore version of the application is simpler than the condition variable implementation, if only because we have hidden the details of all the cond_wait and cond_signal functions inside calls to up and down. Instead of signaling the pool of service threads via a condition variable, the main thread simply raises the next semaphore by one, giving it the value 1. Meanwhile, all the service threads are attempting to decrement this semaphore. One will succeed and receive the new line of input, and the others will fail, continuing to block until the semaphore is raised again. When it has copied the line to its own local variable, the thread raises the main semaphore to tell the main thread that it can proceed to read another line. The concept is recognizably the same as the previous example but is easier to follow.

We have also taken advantage of the fact that semaphores can hold any positive value to terminate the application. When the main thread runs out of input, it simply raises the "next" semaphore to be equal to the number of service threads. At this point, all the threads can decrement the semaphore, read the value of $line that we again set to undef, and quit. If a thread is still busy, the semaphore will remain positive until it finishes and comes back to decrement it—we have no need to put in an extra check in case we missed a signal.

Queues

Many threaded applications, our example a case in point, involve the transport of data between several different threads. In a complex application, incoming data might travel through multiple threads, passed from one to the next before being passed out again: a bucket-chain model. We can create pools of threads at each stage along the chain in a similar way to the preceding example application, but this does not improve upon the mechanism that allows each thread to pass data to the next in line.

The two versions of the application that we have produced so far are limited by the fact that they only handle a single value at a time. Before the main thread can read another line, it has to dispose of the previous one. Even though we can process multiple lines with multiple service threads, the communication between the main thread and the service threads is not very efficient. If we were communicating between different processes, we might use a pipe, which buffers output from one process until the other can read it; the same idea works for threads, too, and takes the form of a queue.

Perl provides support for queues through the Thread::Queue module, which implements simple thread queues in a similar way to the semaphores created by Thread::Semaphore. Rather than a single numeric flag, however, the queue consists of a list to which values may be added at one and removed from the other. At heart this is essentially no more than a shift and pop operation. Using conditional variables and locking the module, however, creates a queue that values may be added to and removed from safely in a threaded environment, following rules similar to those for semaphores:

  • Only one thread may add or remove values in the queue at a time.
  • Any thread may add values to a queue immediately.
  • Any thread may remove values from a queue immediately if there are enough values available in the queue.
  • If a thread attempts to remove more values than are available, it will block until another thread adds sufficient values to the queue.

The Thread::Queue module provides a constructor and four object methods to create and manage queues. The new constructor creates a new queue:

$queue = new Thread::Queue;

Values can be added to the queue, singly or in bulk, with the enqueue method:

$queue->enqueue($value);    # add a single value
$queue->enqueue(@values);   # add several values

A single value can be removed with dequeue. If no value is available, the method will block until one is available:

$value = $queue->dequeue;   # remove a single value, block

If we don't want to risk getting blocked, dequeue_nb removes a single value from a queue, if available, but returns undef immediately, without blocking, if nothing is available:

$value = $queue->dequeue_nb;   # remove a single value, don't block
if (defined $value) {
    ...
}

Finally, to check the number of values in the queue without actually removing one, we have the following pending:

print "There are ",$queue->pending," items in the queue ";

Using a queue, we can rewrite our threaded application again to separate the main thread from the pool of service threads. Since the queue can take multiple values, the main thread no longer has to wait for each value it passes on to be picked up before it can continue. This simplifies both the code and the execution of the program. The queue has no limit, however, so we make sure not to read too much by checking the size of the queue and yielding if it reaches a limit we choose. Here is a revised version of the same application using a queue:

#!/usr/bin/perl
# queue.pl
use warnings;
use strict;

use threads;
use Thread::Queue;
use Thread::Semaphore;

my $threads = 3;        # number of service threads to create
my $maxqueuesize = 5;   # maximum size of queue allowed

my $queue = new Thread::Queue;   # the queue
my $ready = new Thread::Semaphore(0);   # a 'start-gun' semaphore
                                        # initialized to 0 each service
                                        # thread raises it by 1

# a locked print subroutine - stops thread output mingling
sub thr_print : locked {
    print @_;
}

# create a pool of service threads
foreach (1..$threads) {
    threads->create(&process_thing, $ready, $queue);
}

# wait for all service threads to increment semaphore
$ready->down($threads);
# main loop: Read a line, queue it, read another, repeat until done
# yield and wait if the queue gets too large.
while (<>) {
    chomp;
    thr_print "Main thread got '$_' ";

    # stall if we're getting too far ahead of the service threads
    threads->yield while $queue->pending >= $maxqueuesize;

    # queue the new line
    $queue->enqueue($_);
}

thr_print "All lines processed, queuing end signals ";

# to terminate all threads, send as many 'undef's as there are service
# threads
$queue->enqueue( (undef)x$threads );
thr_print "Main thread ended ";
exit 0;

# the thread subroutine--block on lock variable until work arrives
sub process_thing {
    my ($ready,$queue)=@_;

    my $self=threads->self;
    my $thread_line;

    thr_print "Thread ",$self->tid," started ";
    $ready->up; #indicate that we're ready to go

    while (1) {
        # wait for queue to deliver an item
        thr_print "Thread ",$self->tid," waiting ";
        my $thread_line=$queue->dequeue();

        # was this the 'quit' signal? Check the value sent
        last unless (defined $thread_line);

        # do private spurious things to it
        chomp ($thread_line=uc($thread_line));
        thr_print "Thread ",$self->tid," got '$thread_line' ";
    }
    thr_print "Thread ", $self->tid, " ended ";
}

Since the service threads block if no values are waiting in the queue, the problem of having service threads wait is solved for us—we previously dealt with this using condition variables and semaphores. However, we don't need a return semaphore anymore because there is no longer any need for a service thread to signal the main thread that it can continue; the main thread is free to continue as soon as it has copied the new line into the queue.

The means by which we terminate the program has also changed. Originally, we set the line variable to undef and broadcast to all the waiting threads. We replaced that with a semaphore, which we raised high enough so that all service threads could decrement it. With a queue, we use a variation on the semaphore approach, adding sufficient undef values to the queue so that all service threads can remove one and exit.

We have added one further refinement to this version of the application—a "start-gun" semaphore. Simply put, this is a special semaphore that is created with a value of zero and is incremented by one by each service thread as it starts. The main thread attempts to decrement the semaphore by a number equal to the number of service threads, so it will only start to read lines once all service threads are running. Why is this useful? Because threads have no priority of execution. In the previous examples, the first service threads will start receiving and processing lines before later threads have even initialized. In a busy threaded application, the activity of these threads may mean that the service threads may never get the time to initialize themselves properly. In order to make sure we have a full pool of threads at our disposal, we use this semaphore to hold the main thread back until the entire pool is assembled.

Monitoring Thread Status

The Thread::Status module is a handy way to get debugging information from a threaded application. While it can be loaded directly into an application, it is more usual to load it from the command line:

> perl -MThread::Status mythrapp.pl

This will print to standard error, every five seconds, a report of all running threads. We can also control the output destination, output format, and number of stack frames (callers):

> perl -Mthread::Status=output,status.log,format=xml,callers=3 mythrapp.pl

Thread::Status does have one drawback, however: it currently requires Thread::Signal. This was a standard module prior to Perl 5.8 that is now mostly deprecated as a result of the introduction of "safe" signals.

In the older implementation of threads, applications that needed to handle process signals need to use the Thread::Signal module in order to have signals delivered to threads reliably. The newer implementation does not quite replace it, however, so the older version is available from CPAN if needed (for example, for Thread::Status).

Summary

In this chapter, we first looked at sending and receiving signals from Perl processes and writing signal handlers to deal with signals intelligently. We saw how the die and warn functions can be trapped with pseudo-signal handlers and investigated strategies and caveats in the implementation of signal-handling subroutines. We also examined the alarm signal and used it to trigger timed events to abort hung processes.

We went on to example multiprocessing applications and the use of fork, both explicitly and implicitly via open, to start up child processes. When creating child processes, it is very important to manage them properly and in particular collect or reap their exit status when they terminate. Alternatively, a child process can be made independent of its parent by changing its process group, also called daemonizing it. We also looked at communicating between processes using pipes, paired sockets, and Unix System V IPC: message queues, semaphores, and shared memory segments.

While fork is a standard Unix system call, Windows has no equivalent concept, and so Perl instead emulates fork using interpreter threads. This turns out to be a fairly impressive emulation that allows many multiprocessing Perl applications to run on Windows and Unix almost identically.

Finally, we looked at Perl's implementation of threads, newly overhauled in Perl 5.8. The new implementation of threads is called interpreter threads, and it differs from the older version in Perl 5.6 and earlier, in that data is not automatically shared between threads unless and until we ask for it. This is very different to most languages, notably C and C++, and means that the majority of Perl code will run in a threaded environment unaltered without needing to be aware of threads. Windows Perl is automatically threaded because it needs threads to emulate the fork system call. For Unix, we may need to rebuild Perl with thread support enabled in order to use it, as we covered back in Chapter 1.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset