This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
In buildtoc, pull the sanity check for NUL bytes to the top level.
[perl5.git] / pod / perlfork.pod
index 6c11b5e..c09433f 100644 (file)
@@ -4,6 +4,11 @@ perlfork - Perl's fork() emulation
 
 =head1 SYNOPSIS
 
+    NOTE:  As of the 5.8.0 release, fork() emulation has considerably
+    matured.  However, there are still a few known bugs and differences
+    from real fork() that might affect you.  See the "BUGS" and
+    "CAVEATS AND LIMITATIONS" sections below.
+
 Perl provides a fork() keyword that corresponds to the Unix system call
 of the same name.  On most Unix-like platforms where the fork() system
 call is available, Perl's fork() simply calls it.
@@ -11,7 +16,7 @@ call is available, Perl's fork() simply calls it.
 On some platforms such as Windows where the fork() system call is not
 available, Perl can be built to emulate fork() at the interpreter level.
 While the emulation is designed to be as compatible as possible with the
-real fork() at the the level of the Perl program, there are certain
+real fork() at the level of the Perl program, there are certain
 important differences that stem from the fact that all the pseudo child
 "processes" created this way live in the same real process as far as the
 operating system is concerned.
@@ -51,7 +56,7 @@ pseudo-processes are launched after others have been wait()-ed on.
 
 =item %ENV
 
-Each pseudo-process maintains its own virtual enviroment.  Modifications
+Each pseudo-process maintains its own virtual environment.  Modifications
 to %ENV affect the virtual environment, and are only visible within that
 pseudo-process, and in any processes (or pseudo-processes) launched from
 it.
@@ -90,12 +95,15 @@ manipulation functions applied to the ID returned by fork() will affect the
 waiting pseudo-process that called exec(), not the real process it is
 waiting for after the exec().
 
+When exec() is called inside a pseudo-process then DESTROY methods and
+END blocks will still be called after the external process returns.
+
 =item exit()
 
 exit() always exits just the executing pseudo-process, after automatically
 wait()-ing for any outstanding child pseudo-processes.  Note that this means
 that the process as a whole will not exit unless all running pseudo-processes
-have exited.
+have exited.  See below for some limitations with open filehandles.
 
 =item Open handles to files, directories and network sockets
 
@@ -172,6 +180,91 @@ the seek position in the parent will change it in the child and vice-versa.
 One can avoid this by opening files that need distinct seek pointers
 separately in the child.
 
+On some operating systems, notably Solaris and Unixware, calling C<exit()>
+from a child process will flush and close open filehandles in the parent,
+thereby corrupting the filehandles.  On these systems, calling C<_exit()>
+is suggested instead.  C<_exit()> is available in Perl through the 
+C<POSIX> module.  Please consult your system's manpages for more information
+on this.
+
+=item Open directory handles
+
+Perl will completely read from all open directory handles until they
+reach the end of the stream.  It will then seekdir() back to the
+original location and all future readdir() requests will be fulfilled
+from the cache buffer.  That means that neither directory handle held
+by the parent process nor the one held by the child process will see
+any changes made to the directory after the fork() call.
+
+Note that rewinddir() has a similar limitation on Windows and will not
+force readdir() to read the directory again either.  Only a newly
+opened directory handle will reflect changes to the directory.
+
+=item Forking pipe open() not yet implemented
+
+The C<open(FOO, "|-")> and C<open(BAR, "-|")> constructs are not yet
+implemented.  This limitation can be easily worked around in new code
+by creating a pipe explicitly.  The following example shows how to
+write to a forked child:
+
+    # simulate open(FOO, "|-")
+    sub pipe_to_fork ($) {
+       my $parent = shift;
+       pipe my $child, $parent or die;
+       my $pid = fork();
+       die "fork() failed: $!" unless defined $pid;
+       if ($pid) {
+           close $child;
+       }
+       else {
+           close $parent;
+           open(STDIN, "<&=" . fileno($child)) or die;
+       }
+       $pid;
+    }
+
+    if (pipe_to_fork('FOO')) {
+       # parent
+       print FOO "pipe_to_fork\n";
+       close FOO;
+    }
+    else {
+       # child
+       while (<STDIN>) { print; }
+       exit(0);
+    }
+
+And this one reads from the child:
+
+    # simulate open(FOO, "-|")
+    sub pipe_from_fork ($) {
+       my $parent = shift;
+       pipe $parent, my $child or die;
+       my $pid = fork();
+       die "fork() failed: $!" unless defined $pid;
+       if ($pid) {
+           close $child;
+       }
+       else {
+           close $parent;
+           open(STDOUT, ">&=" . fileno($child)) or die;
+       }
+       $pid;
+    }
+
+    if (pipe_from_fork('BAR')) {
+       # parent
+       while (<BAR>) { print; }
+       close BAR;
+    }
+    else {
+       # child
+       print "pipe_from_fork\n";
+       exit(0);
+    }
+
+Forking pipe open() constructs will be supported in future.
+
 =item Global state maintained by XSUBs 
 
 External subroutines (XSUBs) that maintain their own global state may
@@ -215,6 +308,15 @@ representation for pseudo-process IDs will be implemented in future.
 
 =item *
 
+In certain cases, the OS-level handles created by the pipe(), socket(),
+and accept() operators are apparently not duplicated accurately in
+pseudo-processes.  This only happens in some situations, but where it
+does happen, it may result in deadlocks between the read and write ends
+of pipe handles, or inability to send or receive data across socket
+handles.
+
+=item *
+
 This document may be incomplete in some respects.
 
 =back