1 //go:build linux
2 3 package runtime
4 5 import "unsafe"
6 7 // spawnDomain creates a new isolated domain by forking the current process.
8 // The child process executes fn(args) with its own cooperative scheduler.
9 // Communication between parent and child happens over a Unix socketpair.
10 func spawnDomain(fn uintptr, args unsafe.Pointer) {
11 // Create a socketpair for IPC between parent and child.
12 var fds [2]int32
13 r := moxie_socketpair(1, 1, 0, unsafe.Pointer(&fds[0])) // AF_UNIX=1, SOCK_STREAM=1
14 if r < 0 {
15 runtimePanic("spawn: socketpair failed")
16 }
17 18 pid := moxie_fork()
19 if pid < 0 {
20 runtimePanic("spawn: fork failed")
21 }
22 23 if pid == 0 {
24 // Child process — run the spawned function directly.
25 moxie_close(fds[0]) // close parent's end
26 27 // Call the function directly. With no scheduler, the child
28 // domain is single-threaded and runs to completion.
29 spawnCall(fn, args)
30 31 // Exit child process.
32 exit(0)
33 }
34 35 // Parent process.
36 moxie_close(fds[1]) // close child's end
37 38 domainRegister(pid, fds[0])
39 }
40 41 // spawnCall invokes fn(args) directly. The function pointer fn
42 // is a $gowrapper that takes a single pointer argument.
43 func spawnCall(fn uintptr, args unsafe.Pointer) {
44 // The function pointer is a wrapper generated by the compiler
45 // that unpacks args and calls the real function.
46 type funcType func(unsafe.Pointer)
47 (*(*funcType)(unsafe.Pointer(&fn)))(args)
48 }
49 50 // C functions defined in spawn_unix.c
51 52 //export moxie_fork
53 func moxie_fork() int32
54 55 //export moxie_close
56 func moxie_close(fd int32) int32
57 58 //export moxie_socketpair
59 func moxie_socketpair(domain, typ, protocol int32, fds unsafe.Pointer) int32
60