@@ -179,51 +179,6 @@ func pthread_kill(t pthread, sig uint32) {
179
179
}
180
180
func pthread_kill_trampoline ()
181
181
182
- // osinit_hack is a clumsy hack to work around Apple libc bugs
183
- // causing fork+exec to hang in the child process intermittently.
184
- // See go.dev/issue/33565 and go.dev/issue/56784 for a few reports.
185
- //
186
- // The stacks obtained from the hung child processes are in
187
- // libSystem_atfork_child, which is supposed to reinitialize various
188
- // parts of the C library in the new process.
189
- //
190
- // One common stack dies in _notify_fork_child calling _notify_globals
191
- // (inlined) calling _os_alloc_once, because _os_alloc_once detects that
192
- // the once lock is held by the parent process and then calls
193
- // _os_once_gate_corruption_abort. The allocation is setting up the
194
- // globals for the notification subsystem. See the source code at [1].
195
- // To work around this, we can allocate the globals earlier in the Go
196
- // program's lifetime, before any execs are involved, by calling any
197
- // notify routine that is exported, calls _notify_globals, and doesn't do
198
- // anything too expensive otherwise. notify_is_valid_token(0) fits the bill.
199
- //
200
- // The other common stack dies in xpc_atfork_child calling
201
- // _objc_msgSend_uncached which ends up in
202
- // WAITING_FOR_ANOTHER_THREAD_TO_FINISH_CALLING_+initialize. Of course,
203
- // whatever thread the child is waiting for is in the parent process and
204
- // is not going to finish anything in the child process. There is no
205
- // public source code for these routines, so it is unclear exactly what
206
- // the problem is. However, xpc_atfork_child turns out to be exported
207
- // (for use by libSystem_atfork_child, which is in a different library,
208
- // so xpc_atfork_child is unlikely to be unexported any time soon).
209
- // It also stands to reason that since xpc_atfork_child is called at the
210
- // start of any forked child process, it can't be too harmful to call at
211
- // the start of an ordinary Go process. And whatever caches it needs for
212
- // a non-deadlocking fast path during exec empirically do get initialized
213
- // by calling it at startup.
214
- //
215
- // So osinit_hack_trampoline (in sys_darwin_$GOARCH.s) calls
216
- // notify_is_valid_token(0) and xpc_atfork_child(), which makes the
217
- // fork+exec hangs stop happening. If Apple fixes the libc bug in
218
- // some future version of macOS, then we can remove this awful code.
219
- //
220
- //go:nosplit
221
- func osinit_hack () {
222
- libcCall (unsafe .Pointer (abi .FuncPCABI0 (osinit_hack_trampoline )), nil )
223
- return
224
- }
225
- func osinit_hack_trampoline ()
226
-
227
182
// mmap is used to do low-level memory allocation via mmap. Don't allow stack
228
183
// splits, since this function (used by sysAlloc) is called in a lot of low-level
229
184
// parts of the runtime and callers often assume it won't acquire any locks.
@@ -593,6 +548,3 @@ func setNonblock(fd int32) {
593
548
//go:cgo_import_dynamic libc_pthread_cond_wait pthread_cond_wait "/usr/lib/libSystem.B.dylib"
594
549
//go:cgo_import_dynamic libc_pthread_cond_timedwait_relative_np pthread_cond_timedwait_relative_np "/usr/lib/libSystem.B.dylib"
595
550
//go:cgo_import_dynamic libc_pthread_cond_signal pthread_cond_signal "/usr/lib/libSystem.B.dylib"
596
-
597
- //go:cgo_import_dynamic libc_notify_is_valid_token notify_is_valid_token "/usr/lib/libSystem.B.dylib"
598
- //go:cgo_import_dynamic libc_xpc_atfork_child xpc_atfork_child "/usr/lib/libSystem.B.dylib"
0 commit comments