This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Rename ext/Module/Pluggable to ext/Module-Pluggable
[perl5.git] / pod / perlipc.pod
index 8412bfd..416ded5 100644 (file)
@@ -105,9 +105,9 @@ or has changed its UID.
 When directed at a process whose UID is not identical to that
 of the sending process, signal number zero may fail because
 you lack permission to send the signal, even though the process is alive.
-You may be able to determine the cause of failure using C<$!>.
+You may be able to determine the cause of failure using C<%!>.
 
-    unless (kill 0 => $pid or $! == $!{EPERM}) {
+    unless (kill 0 => $pid or $!{EPERM}) {
        warn "$pid looks dead";
     }
 
@@ -119,14 +119,14 @@ handlers:
 But that will be problematic for the more complicated handlers that need
 to reinstall themselves.  Because Perl's signal mechanism is currently
 based on the signal(3) function from the C library, you may sometimes be so
-misfortunate as to run on systems where that function is "broken", that
+unfortunate as to run on systems where that function is "broken", that
 is, it behaves in the old unreliable SysV way rather than the newer, more
 reasonable BSD and POSIX fashion.  So you'll see defensive people writing
 signal handlers like this:
 
     sub REAPER {
        $waitedpid = wait;
-       # loathe sysV: it makes us not only reinstate
+       # loathe SysV: it makes us not only reinstate
        # the handler, but place it after the wait
        $SIG{CHLD} = \&REAPER;
     }
@@ -145,7 +145,7 @@ or better still:
         while (($child = waitpid(-1,WNOHANG)) > 0) {
            $Kid_Status{$child} = $?;
        }
-       $SIG{CHLD} = \&REAPER;  # still loathe sysV
+       $SIG{CHLD} = \&REAPER;  # still loathe SysV
     }
     $SIG{CHLD} = \&REAPER;
     # do something that forks...
@@ -246,7 +246,12 @@ mechanism for processes communicating on the same machine.  It works
 just like a regular, connected anonymous pipes, except that the
 processes rendezvous using a filename and don't have to be related.
 
-To create a named pipe, use the Unix command mknod(1) or on some
+To create a named pipe, use the C<POSIX::mkfifo()> function.
+
+    use POSIX qw(mkfifo);
+    mkfifo($path, 0700) or die "mkfifo $path failed: $!";
+
+You can also use the Unix command mknod(1) or on some
 systems, mkfifo(1).  These may not be in your normal path.
 
     # system return val is backwards, so && not ||
@@ -272,13 +277,13 @@ to find out whether anyone (or anything) has accidentally removed our fifo.
 
     chdir; # go home
     $FIFO = '.signature';
-    $ENV{PATH} .= ":/etc:/usr/games";
 
     while (1) {
        unless (-p $FIFO) {
            unlink $FIFO;
-           system('mknod', $FIFO, 'p')
-               && die "can't mknod $FIFO: $!";
+           require POSIX;
+           POSIX::mkfifo($FIFO, 0700)
+               or die "can't mkfifo $FIFO: $!";
        }
 
        # next line blocks until there's a reader
@@ -288,7 +293,7 @@ to find out whether anyone (or anything) has accidentally removed our fifo.
        sleep 2;    # to avoid dup signals
     }
 
-=head2 Deferred Signals (Safe signals)
+=head2 Deferred Signals (Safe Signals)
 
 In Perls before Perl 5.7.3 by installing Perl code to deal with
 signals, you were exposing yourself to danger from two things.  First,
@@ -304,11 +309,11 @@ There were two things you could do, knowing this: be paranoid or be
 pragmatic.  The paranoid approach was to do as little as possible in your
 signal handler.  Set an existing integer variable that already has a
 value, and return.  This doesn't help you if you're in a slow system call,
-which will just restart.  That means you have to C<die> to longjump(3) out
+which will just restart.  That means you have to C<die> to longjmp(3) out
 of the handler.  Even this is a little cavalier for the true paranoiac,
 who avoids C<die> in a handler because the system I<is> out to get you.
-The pragmatic approach was to say ``I know the risks, but prefer the
-convenience'', and to do anything you wanted in your signal handler,
+The pragmatic approach was to say "I know the risks, but prefer the
+convenience", and to do anything you wanted in your signal handler,
 and be prepared to clean up core dumps now and again.
 
 In Perl 5.7.3 and later to avoid these problems signals are
@@ -325,12 +330,27 @@ previous Perls in the following ways:
 
 =over 4
 
-=item Long running opcodes
+=item Long-running opcodes
+
+As the Perl interpreter only looks at the signal flags when it is about
+to execute a new opcode, a signal that arrives during a long-running
+opcode (e.g. a regular expression operation on a very large string) will
+not be seen until the current opcode completes.
+
+N.B. If a signal of any given type fires multiple times during an opcode 
+(such as from a fine-grained timer), the handler for that signal will
+only be called once after the opcode completes, and all the other
+instances will be discarded.  Furthermore, if your system's signal queue
+gets flooded to the point that there are signals that have been raised
+but not yet caught (and thus not deferred) at the time an opcode
+completes, those signals may well be caught and deferred during
+subsequent opcodes, with sometimes surprising results.  For example, you
+may see alarms delivered even after calling C<alarm(0)> as the latter
+stops the raising of alarms but does not cancel the delivery of alarms
+raised but not yet caught.  Do not depend on the behaviors described in
+this paragraph as they are side effects of the current implementation and
+may change in future versions of Perl.
 
-As Perl interpreter only looks at the signal flags when it about to
-execute a new opcode if a signal arrives during a long running opcode
-(e.g. a regular expression operation on a very large string) then
-signal will not be seen until operation completes.
 
 =item Interrupting IO
 
@@ -355,11 +375,20 @@ with your timeouts.  If you are having problems with such functions,
 you can try using the POSIX sigaction() function, which bypasses the
 Perl safe signals (note that this means subjecting yourself to
 possible memory corruption, as described above).  Instead of setting
-C<$SIG{ALRM}> try something like the following:
+C<$SIG{ALRM}>:
+
+   local $SIG{ALRM} = sub { die "alarm" };
+
+try something like the following:
 
-    use POSIX;
-    sigaction SIGALRM, new POSIX::SigAction sub { die "alarm\n" }
-        or die "Error setting SIGALRM handler: $!\n";
+    use POSIX qw(SIGALRM);
+    POSIX::sigaction(SIGALRM,
+                     POSIX::SigAction->new(sub { die "alarm" }))
+          or die "Error setting SIGALRM handler: $!\n";
+
+Another way to disable the safe signal behavior locally is to use
+the C<Perl::Unsafe::Signals> module from CPAN (which will affect
+all signals).
 
 =item Restartable system calls
 
@@ -377,18 +406,10 @@ C<waitpid> calls will always be retried.
 
 =item Signals as "faults"
 
-Certain signals e.g. SEGV, ILL, BUS are generated as a result of
-virtual memory or other "faults". These are normally fatal and there
-is little a Perl-level handler can do with them. (In particular the
-old signal scheme was particularly unsafe in such cases.)  However if
-a %SIG handler is set the new scheme simply sets a flag and returns as
-described above. This may cause the operating system to try the
-offending machine instruction again and - as nothing has changed - it
-will generate the signal again. The result of this is a rather odd
-"loop". In future Perl's signal mechanism may be changed to avoid this
-- perhaps by simply disallowing %SIG handlers on signals of that
-type. Until then the work-round is not to set a %SIG handler on those
-signals. (Which signals they are is operating system dependant.)
+Certain signals, e.g. SEGV, ILL, and BUS, are generated as a result of
+virtual memory or other "faults". These are normally fatal and there is
+little a Perl-level handler can do with them, so Perl now delivers them
+immediately rather than attempting to defer them.
 
 =item Signals triggered by operating system state
 
@@ -515,14 +536,14 @@ output doesn't wind up on the user's terminal).
                                or die "Can't write to /dev/null: $!";
        defined(my $pid = fork) or die "Can't fork: $!";
        exit if $pid;
-       setsid                  or die "Can't start a new session: $!";
+       die "Can't start a new session: $!" if setsid == -1;
        open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
     }
 
 The fork() has to come before the setsid() to ensure that you aren't a
 process group leader (the setsid() will fail if you are).  If your
 system doesn't have the setsid() function, open F</dev/tty> and use the
-C<TIOCNOTTY> ioctl() on it instead.  See L<tty(4)> for details.
+C<TIOCNOTTY> ioctl() on it instead.  See tty(4) for details.
 
 Non-Unix users should check their Your_OS::Process module for other
 solutions.
@@ -560,7 +581,7 @@ you opened whatever your kid writes to his STDOUT.
        open (FILE, "> /safe/file")
            || die "can't open /safe/file: $!";
        while (<STDIN>) {
-           print FILE; # child's STDIN is parent's KID
+           print FILE; # child's STDIN is parent's KID_TO_WRITE
        }
        exit;  # don't forget this
     }
@@ -616,7 +637,7 @@ the syntax
 
 forks the ps(1) command (without spawning a shell, as there are more than
 three arguments to open()), and reads its standard output via the
-C<KID_PS> filehandle.  The corresponding syntax to read from command
+C<KID_PS> filehandle.  The corresponding syntax to write to command
 pipes (with C<"|-"> in place of C<"-|">) is also implemented.
 
 Note that these operations are full Unix forks, which means they may not be
@@ -905,67 +926,91 @@ go back to service a new client.
     my $paddr;
 
     use POSIX ":sys_wait_h";
+    use Errno;
+
     sub REAPER {
-       my $child;
-        while (($waitedpid = waitpid(-1,WNOHANG)) > 0) {
-           logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
-       }
-       $SIG{CHLD} = \&REAPER;  # loathe sysV
+        local $!;   # don't let waitpid() overwrite current error
+        while ((my $pid = waitpid(-1,WNOHANG)) > 0 && WIFEXITED($?)) {
+            logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
+        }
+        $SIG{CHLD} = \&REAPER;  # loathe SysV
     }
 
     $SIG{CHLD} = \&REAPER;
 
-    for ( $waitedpid = 0;
-         ($paddr = accept(Client,Server)) || $waitedpid;
-         $waitedpid = 0, close Client)
-    {
-       next if $waitedpid and not $paddr;
-       my($port,$iaddr) = sockaddr_in($paddr);
-       my $name = gethostbyaddr($iaddr,AF_INET);
-
-       logmsg "connection from $name [",
-               inet_ntoa($iaddr), "]
-               at port $port";
-
-       spawn sub {
-           $|=1;
-           print "Hello there, $name, it's now ", scalar localtime, $EOL;
-           exec '/usr/games/fortune'           # XXX: `wrong' line terminators
-               or confess "can't exec fortune: $!";
-       };
-
+    while(1) {
+        $paddr = accept(Client, Server) || do {
+            # try again if accept() returned because a signal was received
+            next if $!{EINTR};
+            die "accept: $!";
+        };
+        my ($port, $iaddr) = sockaddr_in($paddr);
+        my $name = gethostbyaddr($iaddr, AF_INET);
+
+        logmsg "connection from $name [",
+               inet_ntoa($iaddr),
+               "] at port $port";
+
+        spawn sub {
+            $|=1;
+            print "Hello there, $name, it's now ", scalar localtime, $EOL;
+            exec '/usr/games/fortune'       # XXX: `wrong' line terminators
+                or confess "can't exec fortune: $!";
+        };
+        close Client;
     }
 
     sub spawn {
-       my $coderef = shift;
+        my $coderef = shift;
 
-       unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
-           confess "usage: spawn CODEREF";
-       }
+        unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
+            confess "usage: spawn CODEREF";
+        }
 
-       my $pid;
-       if (!defined($pid = fork)) {
-           logmsg "cannot fork: $!";
-           return;
-       } elsif ($pid) {
-           logmsg "begat $pid";
-           return; # I'm the parent
-       }
-       # else I'm the child -- go spawn
+        my $pid;
+        if (! defined($pid = fork)) {
+            logmsg "cannot fork: $!";
+            return;
+        } 
+        elsif ($pid) {
+            logmsg "begat $pid";
+            return; # I'm the parent
+        }
+        # else I'm the child -- go spawn
 
-       open(STDIN,  "<&Client")   || die "can't dup client to stdin";
-       open(STDOUT, ">&Client")   || die "can't dup client to stdout";
-       ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
-       exit &$coderef();
+        open(STDIN,  "<&Client")   || die "can't dup client to stdin";
+        open(STDOUT, ">&Client")   || die "can't dup client to stdout";
+        ## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
+        exit &$coderef();
     }
 
-This server takes the trouble to clone off a child version via fork() for
-each incoming request.  That way it can handle many requests at once,
-which you might not always want.  Even if you don't fork(), the listen()
-will allow that many pending connections.  Forking servers have to be
-particularly careful about cleaning up their dead children (called
-"zombies" in Unix parlance), because otherwise you'll quickly fill up your
-process table.
+This server takes the trouble to clone off a child version via fork()
+for each incoming request.  That way it can handle many requests at
+once, which you might not always want.  Even if you don't fork(), the
+listen() will allow that many pending connections.  Forking servers
+have to be particularly careful about cleaning up their dead children
+(called "zombies" in Unix parlance), because otherwise you'll quickly
+fill up your process table.  The REAPER subroutine is used here to
+call waitpid() for any child processes that have finished, thereby
+ensuring that they terminate cleanly and don't join the ranks of the
+living dead.
+
+Within the while loop we call accept() and check to see if it returns
+a false value.  This would normally indicate a system error that needs
+to be reported.  However the introduction of safe signals (see
+L</Deferred Signals (Safe Signals)> above) in Perl 5.7.3 means that
+accept() may also be interrupted when the process receives a signal.
+This typically happens when one of the forked sub-processes exits and
+notifies the parent process with a CHLD signal.  
+
+If accept() is interrupted by a signal then $! will be set to EINTR.
+If this happens then we can safely continue to the next iteration of
+the loop and another call to accept().  It is important that your
+signal handling code doesn't modify the value of $! or this test will
+most likely fail.  In the REAPER subroutine we create a local version
+of $! before calling waitpid().  When waitpid() sets $! to ECHILD (as
+it inevitably does when it has no more children waiting), it will
+update the local copy leaving the original unchanged.
 
 We suggest that you use the B<-T> flag to use taint checking (see L<perlsec>)
 even if we aren't running setuid or setgid.  This is always a good idea
@@ -1002,7 +1047,7 @@ differ from the system on which it's being run:
        my $rtime = '    ';
        read(SOCKET, $rtime, 4);
        close(SOCKET);
-       my $histime = unpack("N", $rtime) - $SECS_of_70_YEARS ;
+       my $histime = unpack("N", $rtime) - $SECS_of_70_YEARS;
        printf "%8d %s\n", $histime - time, ctime($histime);
     }
 
@@ -1030,7 +1075,7 @@ Here's a sample Unix-domain client:
     use strict;
     my ($rendezvous, $line);
 
-    $rendezvous = shift || '/tmp/catsock';
+    $rendezvous = shift || 'catsock';
     socket(SOCK, PF_UNIX, SOCK_STREAM, 0)      || die "socket: $!";
     connect(SOCK, sockaddr_un($rendezvous))    || die "connect: $!";
     while (defined($line = <SOCK>)) {
@@ -1051,7 +1096,7 @@ to be on the localhost, and thus everything works right.
     sub spawn;  # forward declaration
     sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
 
-    my $NAME = '/tmp/catsock';
+    my $NAME = 'catsock';
     my $uaddr = sockaddr_un($NAME);
     my $proto = getprotobyname('tcp');
 
@@ -1070,7 +1115,7 @@ to be on the localhost, and thus everything works right.
         while (($waitedpid = waitpid(-1,WNOHANG)) > 0) {
            logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
        }
-       $SIG{CHLD} = \&REAPER;  # loathe sysV
+       $SIG{CHLD} = \&REAPER;  # loathe SysV
     }
 
     $SIG{CHLD} = \&REAPER;
@@ -1506,7 +1551,7 @@ with TCP, you'd have to use a different socket handle for each host.
        ($hispaddr = recv(SOCKET, $rtime, 4, 0))        || die "recv: $!";
        ($port, $hisiaddr) = sockaddr_in($hispaddr);
        $host = gethostbyaddr($hisiaddr, AF_INET);
-       $histime = unpack("N", $rtime) - $SECS_of_70_YEARS ;
+       $histime = unpack("N", $rtime) - $SECS_of_70_YEARS;
        printf "%-12s ", $host;
        printf "%8d %s\n", $histime - time, scalar localtime($histime);
        $count--;
@@ -1527,10 +1572,10 @@ you weren't wanting it to.
 
 Here's a small example showing shared memory usage.
 
-    use IPC::SysV qw(IPC_PRIVATE IPC_RMID S_IRWXU);
+    use IPC::SysV qw(IPC_PRIVATE IPC_RMID S_IRUSR S_IWUSR);
 
     $size = 2000;
-    $id = shmget(IPC_PRIVATE, $size, S_IRWXU) || die "$!";
+    $id = shmget(IPC_PRIVATE, $size, S_IRUSR|S_IWUSR) || die "$!";
     print "shm key $id\n";
 
     $message = "Message #1";
@@ -1605,12 +1650,12 @@ which is included with Perl starting from Perl 5.005.
 
 A small example demonstrating SysV message queues:
 
-    use IPC::SysV qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRWXU);
+    use IPC::SysV qw(IPC_PRIVATE IPC_RMID IPC_CREAT S_IRUSR S_IWUSR);
 
-    my $id = msgget(IPC_PRIVATE, IPC_CREAT | S_IRWXU);
+    my $id = msgget(IPC_PRIVATE, IPC_CREAT | S_IRUSR | S_IWUSR);
 
     my $sent = "message";
-    my $type = 1234;
+    my $type_sent = 1234;
     my $rcvd;
     my $type_rcvd;
 
@@ -1658,15 +1703,6 @@ signals and to stick with simple TCP and UDP socket operations; e.g., don't
 try to pass open file descriptors over a local UDP datagram socket if you
 want your code to stand a chance of being portable.
 
-As mentioned in the signals section, because few vendors provide C
-libraries that are safely re-entrant, the prudent programmer will do
-little else within a handler beyond setting a numeric variable that
-already exists; or, if locked into a slow (restarting) system call,
-using die() to raise an exception and longjmp(3) out.  In fact, even
-these may in some cases cause a core dump.  It's probably best to avoid
-signals except where they are absolutely inevitable.  This
-will be addressed in a future release of Perl.
-
 =head1 AUTHOR
 
 Tom Christiansen, with occasional vestiges of Larry Wall's original