Skip to content

Commit 5f163a1

Browse files
committed
doc: deepen explanation of functionality, intent and constraints
1 parent e12c2de commit 5f163a1

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

src/os/exec_posix.go

+20-11
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@ func (p *Process) release() error {
3535
return nil
3636
}
3737

38-
// Combination of fork and exec, careful to be thread safe.
39-
40-
// https://cs.opensource.google/go/go/+/master:src/syscall/exec_unix.go;l=143?q=forkExec&ss=go%2Fgo
41-
// losely inspired by the golang implementation
42-
// This is a hacky fire-and forget implementation without setting any attributes, using pipes or checking for errors
38+
// This function is a wrapper around the forkExec function, which is a wrapper around the fork and execve system calls.
39+
// The StartProcess function creates a new process by forking the current process and then calling execve to replace the current process with the new process.
40+
// It thereby replaces the newly created process with the specified command and arguments.
41+
// Differences to upstream golang implementation (https://cs.opensource.google/go/go/+/master:src/syscall/exec_unix.go;l=143):
42+
// * No setting of Process Attributes
43+
// * Ignoring Ctty
44+
// * No ForkLocking (might be introduced by #4273)
45+
// * No parent-child communication via pipes (TODO)
46+
// * No waiting for crashes child processes to prohibit zombie process accumulation / Wait status checking (TODO)
4347
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
44-
// Convert args to C form.
4548
var (
4649
ret uintptr
4750
)
@@ -59,14 +62,16 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
5962
return 0, err
6063
}
6164

62-
// pid, _, _ = syscall.Syscall6(syscall.SYS_FORK, 0, 0, 0, 0, 0, 0)
63-
// 1. fork
65+
if (runtime.GOOS == "freebsd" || runtime.GOOS == "dragonfly") && len(argv) > 0 && len(argv[0]) > len(argv0) {
66+
argvp[0] = argv0p
67+
}
68+
6469
ret, _, _ = syscall.Syscall(syscall.SYS_FORK, 0, 0, 0)
6570
if ret != 0 {
66-
// parent
71+
// if fd == 0 code runs in parent
6772
return int(ret), nil
6873
} else {
69-
// 2. exec
74+
// else code runs in child, which then should exec the new process
7075
ret, _, _ = syscall.Syscall6(syscall.SYS_EXECVE, uintptr(unsafe.Pointer(argv0p)), uintptr(unsafe.Pointer(&argvp[0])), uintptr(unsafe.Pointer(&envvp[0])), 0, 0, 0)
7176
if ret != 0 {
7277
// exec failed
@@ -77,7 +82,11 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
7782
}
7883
}
7984

80-
// in regular go this is where the forkExec thingy comes in play
85+
// In Golang, the idiomatic way to create a new process is to use the StartProcess function.
86+
// Since the Model of operating system processes in tinygo differs from the one in Golang, we need to implement the StartProcess function differently.
87+
// The startProcess function is a wrapper around the forkExec function, which is a wrapper around the fork and execve system calls.
88+
// The StartProcess function creates a new process by forking the current process and then calling execve to replace the current process with the new process.
89+
// It thereby replaces the newly created process with the specified command and arguments.
8190
func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
8291
pid, err := ForkExec(name, argv, attr)
8392
if err != nil {

src/syscall/syscall.go

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package syscall
33
import (
44
"errors"
55
"sync/atomic"
6-
"internal/bytealg"
76

87
"github.com/tinygo-org/tinygo/src/internal/bytealg"
98
)

0 commit comments

Comments
 (0)