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 tag | macOS | # |
|---|---|---|
| xnu-1456.1.26 | macOS 10.6 Snow Leopard | 2 |
| xnu-1486.2.11 | — | 2 |
| xnu-1504.15.3 | — | 2 |
| xnu-1504.3.12 | — | 2 |
| xnu-1504.7.4 | — | 2 |
| xnu-1504.9.17 | — | 2 |
| xnu-1504.9.26 | — | 2 |
| xnu-1504.9.37 | — | 2 |
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