# perldoc > fork

---
type: CommandReference
command: perlfork
mode: perldoc
section: "1"
source: perldoc
---

## Quick Reference

- `$pid = fork()` — spawn a pseudo-process; returns PID to parent, 0 to child
- `waitpid($pid, 0)` — wait for a specific pseudo-process to terminate
- `kill('TERM', $pid)` — send signal to pseudo-process (unreliable; avoid KILL)
- Simulate `open(FOO, "|-")` using explicit pipe and fork (see Examples)
- Simulate `open(BAR, "-|")` using explicit pipe and fork (see Examples)
- `chdir` works virtually within each pseudo-process
- `%ENV` modifications are isolated per pseudo-process
- `exit` in a child pseudo-process only exits that child, not the parent

## Name

**perlfork** - Perl's fork() emulation

## Synopsis

Perl provides a `fork()` keyword that corresponds to the Unix system call. On most Unix-like platforms it calls the real `fork()`. On platforms without `fork()` (e.g. Windows), Perl emulates it at the interpreter level. All pseudo-processes live in the same OS process as threads. The emulation is transparent to Perl code but has important differences.

## Description

The fork() emulation clones the entire interpreter and runs it in a separate thread (pseudo-process). The parent returns the pseudo-process ID; the child returns 0.

### Behavior of Perl features in pseudo-processes

- **`$$` or `$PROCESS_ID`** — correctly set to pseudo-process ID; subject to recycling.
- **`%ENV`** — each pseudo-process has its own virtual environment; modifications are isolated.
- **`chdir()`** — each pseudo-process has its own virtual current directory; all file accesses map correctly.
- **`wait()` and `waitpid()`** — accept pseudo-process IDs; wait for termination and return status.
- **`kill()`** — can be used on pseudo-processes, but outcomes are unpredictable. `kill('KILL', ...)` may cause memory leaks and hangs. `kill('TERM', ...)` is not delivered while the pseudo-process is blocked on a system call. Starting in Perl 5.14, the parent does not wait for children signalled with TERM; you must call `waitpid()` explicitly.
- **`exec()`** — inside a pseudo-process, `exec()` spawns a real external process and waits for it. The process ID reported inside the executable differs from the fork() return. DESTROY and END blocks still run after the external process returns.
- **`exit()`** — exits only the calling pseudo-process; the parent does not exit until all pseudo-children have exited.
- **Open handles** — all file, directory, and socket handles are dup()-ed; closing in one process does not affect others. Seek pointers are shared.

### Resource limits

Because pseudo-processes are threads in the same OS process, OS-level limits (file handles, memory, CPU, etc.) apply to all pseudo-processes collectively.

### Killing the parent process

If the parent is killed (via `kill()` or external means), all pseudo-processes are killed immediately.

### Lifetime and parent/child waiting

Normally, the parent and each pseudo-parent wait for their pseudo-children to exit before they exit. Starting in Perl 5.14, a parent will not automatically wait for a child that received `kill('TERM', ...)` (to avoid deadlock).

## Caveats and Limitations

- **BEGIN blocks** — `fork()` inside a BEGIN block does not work correctly. The forked copy runs the BEGIN block but does not continue parsing the source stream after it. Example:
  ```perl
  BEGIN {
      fork and exit;          # fork child and exit the parent
      print "inner\n";
  }
  print "outer\n";
  
  Prints only `inner`.

- **Open filehandles** — dup()-ed handles share the same seek pointer. Changes in parent affect child and vice versa. Open files separately if distinct seek pointers are needed. On Solaris and Unixware, calling `exit()` from a child flushes/closes filehandles in the parent; use `POSIX::_exit()` instead.

- **Open directory handles** — after `fork()`, Perl reads all directory entries into a cache; future `readdir()` calls use the cache. Neither parent nor child sees directory changes made after the fork. `rewinddir()` does not force a re-read; only a newly opened handle reflects changes.

- **Forking pipe open() not yet implemented** — `open(FOO, "|-")` and `open(BAR, "-|")` are not supported. Use explicit `pipe()`, `fork()`, and `open()` to simulate. See Examples.

- **Global state in XSUBs** — external subroutines that maintain their own global state may not work correctly. They must either lock or store state on the Perl symbol table.

- **Interpreter embedded in larger application** — the emulation only knows about the Perl interpreter's data structures; application state (e.g., call stack) is out of reach.

- **Thread-safety of extensions** — extensions calling non-thread-safe libraries may fail when `fork()` is used.

## Portability Caveats

- **`kill(9, $child)`** must not be used on forked processes; it is unsafe and has unpredictable results.

## Bugs

- Pseudo-process IDs are negative integers, which breaks `wait()` and `waitpid()` for the value -1. The current implementation assumes the system never allocates a thread ID of 1 for user threads.
- OS-level handles from `pipe()`, `socket()`, and `accept()` may not be duplicated accurately in pseudo-processes, potentially causing deadlocks.
- This document may be incomplete.

## Examples

### Simulate `open(FOO, "|-")` (write to forked child)

perl
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);
}
### Simulate `open(BAR, "-|")` (read from forked child)

perl
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);
}
## See Also

- `fork` in perlfunc
- [perlipc](https://perldoc.perl.org/perlipc)