Each pseudo-process maintains its own virtual enviroment. 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.
<P></P>
<DT><STRONG><A NAME="item_chdir"><CODE>chdir()</CODE> and all other builtins that accept filenames</A></STRONG><BR>
<DD>
Each pseudo-process maintains its own virtual idea of the current directory.
Modifications to the current directory using <A HREF="#item_chdir"><CODE>chdir()</CODE></A> are only visible within
that pseudo-process, and in any processes (or pseudo-processes) launched from
it. All file and directory accesses from the pseudo-process will correctly
map the virtual working directory to the real working directory appropriately.
<P></P>
<DT><STRONG><A NAME="item_wait"><CODE>wait()</CODE> and <A HREF="../../lib/Pod/perlfunc.html#item_waitpid"><CODE>waitpid()</CODE></A></A></STRONG><BR>
<DD>
<A HREF="#item_wait"><CODE>wait()</CODE></A> and <A HREF="../../lib/Pod/perlfunc.html#item_waitpid"><CODE>waitpid()</CODE></A> can be passed a pseudo-process ID returned by fork().
These calls will properly wait for the termination of the pseudo-process
Any filehandles open at the time of the <A HREF="../../lib/Pod/perlfunc.html#item_fork"><CODE>fork()</CODE></A> will be dup()-ed. Thus,
the files can be closed independently in the parent and child, but beware
that the dup()-ed handles will still share the same seek pointer. Changing
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.
<P></P>
<DT><STRONG><A NAME="item_open">Forking pipe <CODE>open()</CODE> not yet implemented</A></STRONG><BR>
<DD>
The <A HREF="#item_open"><CODE>open(FOO, "|-")</CODE></A> and <A HREF="#item_open"><CODE>open(BAR, "-|")</CODE></A> 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:
<PRE>
# 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;
}</PRE>
<PRE>
if (pipe_to_fork('FOO')) {
# parent
print FOO "pipe_to_fork\n";
close FOO;
}
else {
# child
while (<STDIN>) { print; }
close STDIN;
exit(0);
}</PRE>
<P>And this one reads from the child:</P>
<PRE>
# 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;
}</PRE>
<PRE>
if (pipe_from_fork('BAR')) {
# parent
while (<BAR>) { print; }
close BAR;
}
else {
# child
print "pipe_from_fork\n";
close STDOUT;
exit(0);
}</PRE>
<P>Forking pipe <A HREF="#item_open"><CODE>open()</CODE></A> constructs will be supported in future.</P>
<P></P>
<DT><STRONG><A NAME="item_Global_state_maintained_by_XSUBs">Global state maintained by XSUBs</A></STRONG><BR>
<DD>
External subroutines (XSUBs) that maintain their own global state may
not work correctly. Such XSUBs will either need to maintain locks to
protect simultaneous access to global data from different pseudo-processes,
or maintain all their state on the Perl symbol table, which is copied
naturally when <A HREF="../../lib/Pod/perlfunc.html#item_fork"><CODE>fork()</CODE></A> is called. A callback mechanism that provides
extensions an opportunity to clone their state will be provided in the
near future.
<P></P>
<DT><STRONG><A NAME="item_Interpreter_embedded_in_larger_application">Interpreter embedded in larger application</A></STRONG><BR>
<DD>
The <A HREF="../../lib/Pod/perlfunc.html#item_fork"><CODE>fork()</CODE></A> emulation may not behave as expected when it is executed in an
application which embeds a Perl interpreter and calls Perl APIs that can
evaluate bits of Perl code. This stems from the fact that the emulation
only has knowledge about the Perl interpreter's own data structures and
knows nothing about the containing application's state. For example, any
state carried on the application's own call stack is out of reach.
<P></P>
<DT><STRONG><A NAME="item_Thread%2Dsafety_of_extensions">Thread-safety of extensions</A></STRONG><BR>
<DD>
Since the <A HREF="../../lib/Pod/perlfunc.html#item_fork"><CODE>fork()</CODE></A> emulation runs code in multiple threads, extensions
calling into non-thread-safe libraries may not work reliably when
calling fork(). As Perl's threading support gradually becomes more
widely adopted even on platforms with a native fork(), such extensions
are expected to be fixed for thread-safety.
<P></P></DL>
<P>
<HR>
<H1><A NAME="bugs">BUGS</A></H1>
<UL>
<LI>
Having pseudo-process IDs be negative integers breaks down for the integer
<CODE>-1</CODE> because the <A HREF="#item_wait"><CODE>wait()</CODE></A> and <A HREF="../../lib/Pod/perlfunc.html#item_waitpid"><CODE>waitpid()</CODE></A> functions treat this number as
being special. The tacit assumption in the current implementation is that
the system never allocates a thread ID of <CODE>1</CODE> for user threads. A better
representation for pseudo-process IDs will be implemented in future.
<P></P>
<LI>
This document may be incomplete in some respects.
<P></P></UL>
<P>
<HR>
<H1><A NAME="author">AUTHOR</A></H1>
<P>Support for concurrent interpreters and the <A HREF="../../lib/Pod/perlfunc.html#item_fork"><CODE>fork()</CODE></A> emulation was implemented
by ActiveState, with funding from Microsoft Corporation.</P>
<P>This document is authored and maintained by Gurusamy Sarathy