fork() creates a child process. In the child (pid == 0), call execvp immediately to replace the process image — the Boehm GC requires this pattern since the child inherits an inconsistent GC state. waitpid in the parent blocks until the child exits.
// Fork and exec — running external commands // Fork y exec — ejecutar comandos externos fn main() -> int { let pid: int = fork() if pid == 0 { // Child process: exec immediately (GC requirement) let args: Array = ["echo", "hello from child"] execvp("echo", args) // execvp replaces the process — this line never runs return 1 } if pid > 0 { // Parent: wait for child to finish print("parent: spawned child " + int_to_string(pid)) let status: int = waitpid(pid, 0) print("parent: child exited with " + int_to_string(status)) } else { print("fork failed") } return 0 }
parent: spawned child 12345 hello from child parent: child exited with 0
How it works
fork() duplicates the current process. It returns 0 in the child and the child's PID in the parent. Because Nyx uses the Boehm garbage collector, the child process must not allocate GC-managed memory — it must call execvp() immediately to replace its process image with a new program.
execvp(command, args) replaces the current process with the given command. The first element of args is conventionally the program name. If execvp succeeds, it never returns.
waitpid(pid, 0) blocks the parent until the child exits and returns the exit status. This is the standard Unix pattern for spawning subprocesses.