//go:build linux package runtime import "unsafe" // spawnDomain creates a new isolated domain by forking the current process. // The child process executes fn(args) with its own cooperative scheduler. // Communication between parent and child happens over a Unix socketpair. func spawnDomain(fn uintptr, args unsafe.Pointer) { // Create a socketpair for IPC between parent and child. var fds [2]int32 r := moxie_socketpair(1, 1, 0, unsafe.Pointer(&fds[0])) // AF_UNIX=1, SOCK_STREAM=1 if r < 0 { runtimePanic("spawn: socketpair failed") } pid := moxie_fork() if pid < 0 { runtimePanic("spawn: fork failed") } if pid == 0 { // Child process — run the spawned function directly. moxie_close(fds[0]) // close parent's end // Call the function directly. With no scheduler, the child // domain is single-threaded and runs to completion. spawnCall(fn, args) // Exit child process. exit(0) } // Parent process. moxie_close(fds[1]) // close child's end domainRegister(pid, fds[0]) } // spawnCall invokes fn(args) directly. The function pointer fn // is a $gowrapper that takes a single pointer argument. func spawnCall(fn uintptr, args unsafe.Pointer) { // The function pointer is a wrapper generated by the compiler // that unpacks args and calls the real function. type funcType func(unsafe.Pointer) (*(*funcType)(unsafe.Pointer(&fn)))(args) } // C functions defined in spawn_unix.c //export moxie_fork func moxie_fork() int32 //export moxie_close func moxie_close(fd int32) int32 //export moxie_socketpair func moxie_socketpair(domain, typ, protocol int32, fds unsafe.Pointer) int32