Skip to content

Commit 6c9b661

Browse files
committed
runtime: revert Apple libc atfork workaround
Revert CL 451735 (1f4394a), which fixed #33565 and #56784 but also introduced #57263. I have a different fix to apply instead. Since the first fix was never backported, it will be easiest to backport the new fix if the new fix is done in a separate CL from the revert. Change-Id: I6c8ea3a46e542ee4702675bbc058e29ccd2723e0 Reviewed-on: https://go-review.googlesource.com/c/go/+/459175 Reviewed-by: Cherry Mui <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Russ Cox <[email protected]>
1 parent 6d3139b commit 6c9b661

File tree

4 files changed

+0
-65
lines changed

4 files changed

+0
-65
lines changed

src/runtime/os_darwin.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ func osinit() {
136136

137137
ncpu = getncpu()
138138
physPageSize = getPageSize()
139-
140-
osinit_hack()
141139
}
142140

143141
func sysctlbynameInt32(name []byte) (int32, int32) {

src/runtime/sys_darwin.go

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -179,51 +179,6 @@ func pthread_kill(t pthread, sig uint32) {
179179
}
180180
func pthread_kill_trampoline()
181181

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-
227182
// mmap is used to do low-level memory allocation via mmap. Don't allow stack
228183
// splits, since this function (used by sysAlloc) is called in a lot of low-level
229184
// parts of the runtime and callers often assume it won't acquire any locks.
@@ -593,6 +548,3 @@ func setNonblock(fd int32) {
593548
//go:cgo_import_dynamic libc_pthread_cond_wait pthread_cond_wait "/usr/lib/libSystem.B.dylib"
594549
//go:cgo_import_dynamic libc_pthread_cond_timedwait_relative_np pthread_cond_timedwait_relative_np "/usr/lib/libSystem.B.dylib"
595550
//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"

src/runtime/sys_darwin_amd64.s

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -597,15 +597,6 @@ TEXT runtime·pthread_kill_trampoline(SB),NOSPLIT,$0
597597
POPQ BP
598598
RET
599599

600-
TEXT runtime·osinit_hack_trampoline(SB),NOSPLIT,$0
601-
PUSHQ BP
602-
MOVQ SP, BP
603-
MOVQ $0, DI // arg 1 val
604-
CALL libc_notify_is_valid_token(SB)
605-
CALL libc_xpc_atfork_child(SB)
606-
POPQ BP
607-
RET
608-
609600
// syscall calls a function in libc on behalf of the syscall package.
610601
// syscall takes a pointer to a struct like:
611602
// struct {

src/runtime/sys_darwin_arm64.s

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -458,12 +458,6 @@ TEXT runtime·pthread_setspecific_trampoline(SB),NOSPLIT,$0
458458
BL libc_pthread_setspecific(SB)
459459
RET
460460

461-
TEXT runtime·osinit_hack_trampoline(SB),NOSPLIT,$0
462-
MOVD $0, R0 // arg 1 val
463-
BL libc_notify_is_valid_token(SB)
464-
BL libc_xpc_atfork_child(SB)
465-
RET
466-
467461
// syscall calls a function in libc on behalf of the syscall package.
468462
// syscall takes a pointer to a struct like:
469463
// struct {

0 commit comments

Comments
 (0)