Skip to content
BSD syscall#2

svc · unix #2

fork

Duplicates the calling process, returning the child PID in the parent and 0 in the child.

Prototype

int fork(void);

Returns: int

Version history

XNU tagmacOS#
xnu-1456.1.26macOS 10.6 Snow Leopard2
xnu-1486.2.112
xnu-1504.15.32
xnu-1504.3.122
xnu-1504.7.42
xnu-1504.9.172
xnu-1504.9.262
xnu-1504.9.372

Examples

Classic fork/exec

#include <unistd.h>
#include <sys/wait.h>

pid_t pid = fork();
if (pid == 0) {
    execlp("/bin/ls", "ls", "-l", NULL);
    _exit(127);
}
int status;
waitpid(pid, &status, 0);

Notes

XNU's fork() clones the BSD proc struct, then creates a new Mach task whose address space is mapped copy-on-write from the parent. The child inherits open file descriptors, signal mask, cwd, and resource limits, but loses pending timers, async I/O, and most pthread state. Apple has long discouraged fork() in apps that link Cocoa or CoreFoundation: only async-signal-safe work is legal between fork() and execve().

Detection

Endpoint Security exposes ES_EVENT_TYPE_NOTIFY_FORK with the child es_process_t. DTrace syscall::fork:return reports the child PID in arg0 from the parent context.

Related APIs

vforkexecveposix_spawnwait4waitidexit