Skip to content

Commit

Permalink
syscall, internal/poll: fall back to accept on linux-arm
Browse files Browse the repository at this point in the history
Our minimum Linux version is 2.6.32, and the accept4 system call was
introduced in 2.6.28, so we use accept4 everywhere. Unfortunately,
it turns out that the accept4 system call was only added to
linux-arm in 2.6.36, so for linux-arm only we need to try the accept4
system call and then fall back to accept if it doesn't work.

The code we use on linux-arm is the code we used in Go 1.17.
On non-arm platforms we continue using the simpler code introduced
in Go 1.18.

Adding accept4 to the ARM Linux kernel was:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=21d93e2e29722d7832f61cc56d73fb953ee6578e

Fixes #57333

Change-Id: I6680cb54dd4d3514a6887dda8906e6708c64459d
Reviewed-on: https://go-review.googlesource.com/c/go/+/457995
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
  • Loading branch information
ianlancetaylor authored and gopherbot committed Dec 16, 2022
1 parent 3323dab commit 24ac659
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/internal/poll/sock_cloexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// This file implements accept for platforms that provide a fast path for
// setting SetNonblock and CloseOnExec.

//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris
//go:build dragonfly || freebsd || (linux && !arm) || netbsd || openbsd || solaris

package poll

Expand Down
51 changes: 51 additions & 0 deletions src/internal/poll/sock_cloexec_accept.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements accept for platforms that provide a fast path for
// setting SetNonblock and CloseOnExec, but don't necessarily have accept4.
// This is the code we used for accept in Go 1.17 and earlier.
// On Linux the accept4 system call was introduced in 2.6.28 kernel,
// and our minimum requirement is 2.6.32, so we simplified the function.
// Unfortunately, on ARM accept4 wasn't added until 2.6.36, so for ARM
// only we continue using the older code.

//go:build linux && arm

package poll

import "syscall"

// Wrapper around the accept system call that marks the returned file
// descriptor as nonblocking and close-on-exec.
func accept(s int) (int, syscall.Sockaddr, string, error) {
ns, sa, err := Accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
switch err {
case nil:
return ns, sa, "", nil
default: // errors other than the ones listed
return -1, sa, "accept4", err
case syscall.ENOSYS: // syscall missing
case syscall.EINVAL: // some Linux use this instead of ENOSYS
case syscall.EACCES: // some Linux use this instead of ENOSYS
case syscall.EFAULT: // some Linux use this instead of ENOSYS
}

// See ../syscall/exec_unix.go for description of ForkLock.
// It is probably okay to hold the lock across syscall.Accept
// because we have put fd.sysfd into non-blocking mode.
// However, a call to the File method will put it back into
// blocking mode. We can't take that risk, so no use of ForkLock here.
ns, sa, err = AcceptFunc(s)
if err == nil {
syscall.CloseOnExec(ns)
}
if err != nil {
return -1, nil, "accept", err
}
if err = syscall.SetNonblock(ns, true); err != nil {
CloseFunc(ns)
return -1, nil, "setnonblock", err
}
return ns, sa, "", nil
}
15 changes: 0 additions & 15 deletions src/syscall/syscall_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,21 +643,6 @@ func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
return nil, EAFNOSUPPORT
}

func Accept(fd int) (nfd int, sa Sockaddr, err error) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
nfd, err = accept4(fd, &rsa, &len, 0)
if err != nil {
return
}
sa, err = anyToSockaddr(&rsa)
if err != nil {
Close(nfd)
nfd = 0
}
return
}

func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
Expand Down
34 changes: 34 additions & 0 deletions src/syscall/syscall_linux_accept.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// We require Linux kernel version 2.6.32. The accept4 system call was
// added in version 2.6.28, so in general we can use accept4.
// Unfortunately, for ARM only, accept4 was added in version 2.6.36.
// Handle that case here, by using a copy of the Accept function that
// we used in Go 1.17.

//go:build linux && arm

package syscall

//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)

func Accept(fd int) (nfd int, sa Sockaddr, err error) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
// Try accept4 first for Android and newer kernels.
nfd, err = accept4(fd, &rsa, &len, 0)
if err == ENOSYS {
nfd, err = accept(fd, &rsa, &len)
}
if err != nil {
return
}
sa, err = anyToSockaddr(&rsa)
if err != nil {
Close(nfd)
nfd = 0
}
return
}
25 changes: 25 additions & 0 deletions src/syscall/syscall_linux_accept4.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file provides the Accept function used on all systems
// other than arm. See syscall_linux_accept.go for why.

//go:build linux && !arm

package syscall

func Accept(fd int) (nfd int, sa Sockaddr, err error) {
var rsa RawSockaddrAny
var len _Socklen = SizeofSockaddrAny
nfd, err = accept4(fd, &rsa, &len, 0)
if err != nil {
return
}
sa, err = anyToSockaddr(&rsa)
if err != nil {
Close(nfd)
nfd = 0
}
return
}
13 changes: 12 additions & 1 deletion src/syscall/zsyscall_linux_arm.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 24ac659

Please sign in to comment.