@@ -9,6 +9,7 @@ package os
9
9
import (
10
10
"runtime"
11
11
"syscall"
12
+ "unsafe"
12
13
)
13
14
14
15
// The only signal values guaranteed to be present in the os package on all
@@ -33,3 +34,55 @@ func (p *Process) release() error {
33
34
runtime .SetFinalizer (p , nil )
34
35
return nil
35
36
}
37
+
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
43
+ func forkExec (argv0 string , argv []string , attr * ProcAttr ) (pid int , err error ) {
44
+ // Convert args to C form.
45
+ var (
46
+ ret uintptr
47
+ )
48
+
49
+ argv0p , err := syscall .BytePtrFromString (argv0 )
50
+ if err != nil {
51
+ return 0 , err
52
+ }
53
+ argvp , err := syscall .SlicePtrFromStrings (argv )
54
+ if err != nil {
55
+ return 0 , err
56
+ }
57
+ envvp , err := syscall .SlicePtrFromStrings (attr .Env )
58
+ if err != nil {
59
+ return 0 , err
60
+ }
61
+
62
+ // pid, _, _ = syscall.Syscall6(syscall.SYS_FORK, 0, 0, 0, 0, 0, 0)
63
+ // 1. fork
64
+ ret , _ , _ = syscall .Syscall (syscall .SYS_FORK , 0 , 0 , 0 )
65
+ if ret != 0 {
66
+ // parent
67
+ return int (ret ), nil
68
+ } else {
69
+ // 2. exec
70
+ ret , _ , _ = syscall .Syscall6 (syscall .SYS_EXECVE , uintptr (unsafe .Pointer (argv0p )), uintptr (unsafe .Pointer (& argvp [0 ])), uintptr (unsafe .Pointer (& envvp [0 ])), 0 , 0 , 0 )
71
+ if ret != 0 {
72
+ // exec failed
73
+ syscall .Exit (1 )
74
+ }
75
+ // 3. TODO: use pipes to communicate back child status
76
+ return int (ret ), nil
77
+ }
78
+ }
79
+
80
+ // in regular go this is where the forkExec thingy comes in play
81
+ func startProcess (name string , argv []string , attr * ProcAttr ) (p * Process , err error ) {
82
+ pid , err := ForkExec (name , argv , attr )
83
+ if err != nil {
84
+ return nil , err
85
+ }
86
+
87
+ return findProcess (pid )
88
+ }
0 commit comments