Commit 628c5e6
committed
os: start processes with posix_spawn
The process layer was a stub. StartProcess refused every ProcAttr that carried
Dir, Sys or Files, and os/exec always passes three Files, so no command could
run. Wait, Kill and Signal returned ErrNotImplemented, and ProcessState was an
empty struct whose methods all reported a failure. The code that did exist was
a fork() and an execve() with no branch on the result of the fork, so the
parent fell into the exec as well.
Use posix_spawn(3) on hosted Linux and macOS, which are the two targets where
the standard library os/exec and syscall packages compile against this
override. Those targets run the threads scheduler and collect with Boehm, so a
fork from Go gives the child one thread that holds the locks of the other
threads, malloc among them, and the stop-the-world signal of the collector can
arrive between the fork and the exec. posix_spawn does the clone and the exec
inside libc, where no Go code runs, and it reports a failed exec as its return
value, so the usual status pipe is not necessary.
The descriptors of the child come from a file-actions list. There is a dup2 for
each entry of ProcAttr.Files, a close for a missing one, and an addchdir_np for
Dir. A nil Env means the environment of the parent, as Go documents. The
attribute block installs an empty signal mask, because a blocked mask survives
an exec and the spawning thread can carry the signal of the collector blocked.
Setpgid and Pgid are honoured through posix_spawnattr_setpgroup, which is the
one SysProcAttr request that posix_spawn can express. Every other field is
refused by name, and the error unwraps to ErrNotImplementedSys.
Wait reaps with wait4 and retries on EINTR, which a thread in wait4 gets as a
matter of course, because the collector interrupts it. ProcessState now carries
the pid and the real syscall.WaitStatus, so exec.ExitError reports "exit status
N", and ExitCode, Exited, Success and Sys work. A killed child is reported as
signalled. Signal refuses a pid that Wait reaped and maps ESRCH to
ErrProcessDone, which is what exec.CommandContext expects when its context
fires as the command finishes.
macOS has no pipe2, so os.Pipe there marks both descriptors close-on-exec
afterwards, under ForkLock. Without the flag every pipe goes into every child,
and a child that holds a copy of a write end keeps that pipe from a report of
EOF. Linux asks for O_CLOEXEC in pipe2 and gets it atomically.
The minimal macOS SDK in lib/macos-minimal-sdk does not declare <spawn.h>, so
the generated libSystem stub has none of the posix_spawn symbols and a darwin
program that starts a process does not link. The builder now assembles the
missing names into a second stub object. posix_spawn_file_actions_addchdir_np
came with macOS 10.15, so a binary from this toolchain needs at least that
release.
Targets without a process model keep the previous stubs. Only the build tag on
exec_other.go changes, to let macOS through to the new implementation.1 parent c3bdc58 commit 628c5e6
11 files changed
Lines changed: 932 additions & 284 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
11 | 35 | | |
12 | 36 | | |
13 | 37 | | |
| |||
36 | 60 | | |
37 | 61 | | |
38 | 62 | | |
39 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
40 | 91 | | |
41 | 92 | | |
42 | 93 | | |
| |||
48 | 99 | | |
49 | 100 | | |
50 | 101 | | |
| 102 | + | |
51 | 103 | | |
52 | 104 | | |
53 | 105 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
8 | 11 | | |
9 | 12 | | |
10 | 13 | | |
| |||
36 | 39 | | |
37 | 40 | | |
38 | 41 | | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | 42 | | |
67 | 43 | | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
68 | 48 | | |
69 | 49 | | |
70 | 50 | | |
| |||
73 | 53 | | |
74 | 54 | | |
75 | 55 | | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | 56 | | |
92 | 57 | | |
93 | 58 | | |
| |||
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
21 | 64 | | |
22 | 65 | | |
23 | 66 | | |
| |||
0 commit comments