mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
os: make FindProcess use pidfd on Linux
Amend FindProcess to use pidfdFind, and make it return ErrProcessDone if pidfdFind is used and the process is not found. Since this is a change in API, introduce GODEBUG osfinderr=0 setting to disable the feature. Change-Id: I724c6f622f0c99f21a70b864cf7cf2b8836869ee Reviewed-on: https://go-review.googlesource.com/c/go/+/542699 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
ccb6077d11
commit
cdf3249d74
7 changed files with 50 additions and 3 deletions
|
|
@ -126,6 +126,11 @@ for example,
|
|||
see the [runtime documentation](/pkg/runtime#hdr-Environment_Variables)
|
||||
and the [go command documentation](/cmd/go#hdr-Build_and_test_caching).
|
||||
|
||||
### Go 1.23
|
||||
|
||||
Go 1.23 enabled Linux pidfd support for process lookup. This feature can be
|
||||
disabled by using the [`osfinderr` setting](/pkg/os#FindProcess).
|
||||
|
||||
### Go 1.22
|
||||
|
||||
Go 1.22 adds a configurable limit to control the maximum acceptable RSA key size
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ var All = []Info{
|
|||
{Name: "multipartmaxparts", Package: "mime/multipart"},
|
||||
{Name: "multipathtcp", Package: "net"},
|
||||
{Name: "netdns", Package: "net", Opaque: true},
|
||||
{Name: "osfinderr", Package: "os"},
|
||||
{Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"},
|
||||
{Name: "randautoseed", Package: "math/rand"},
|
||||
{Name: "tarinsecurepath", Package: "archive/tar"},
|
||||
|
|
|
|||
|
|
@ -86,10 +86,17 @@ func Getppid() int { return syscall.Getppid() }
|
|||
// The Process it returns can be used to obtain information
|
||||
// about the underlying operating system process.
|
||||
//
|
||||
// On Unix systems, FindProcess always succeeds and returns a Process
|
||||
// On Unix systems other than Linux, FindProcess always succeeds and returns a Process
|
||||
// for the given pid, regardless of whether the process exists. To test whether
|
||||
// the process actually exists, see whether p.Signal(syscall.Signal(0)) reports
|
||||
// an error.
|
||||
//
|
||||
// On Linux, FindProcess may either return ErrProcessGone for a non-existing
|
||||
// process (thus eliminating the need to use a signal to check if the process
|
||||
// exists), or work the same way as for other Unix systems, described above,
|
||||
// depending on the kernel version used and the system configuration. The old
|
||||
// behavior (of always succeeding) can be enforced by using GODEBUG setting
|
||||
// osfinderr=0.
|
||||
func FindProcess(pid int) (*Process, error) {
|
||||
return findProcess(pid)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,8 +106,14 @@ func (p *Process) release() error {
|
|||
}
|
||||
|
||||
func findProcess(pid int) (p *Process, err error) {
|
||||
// NOOP for unix.
|
||||
return newProcess(pid, unsetHandle), nil
|
||||
h, err := pidfdFind(pid)
|
||||
if err == ErrProcessDone {
|
||||
return nil, err
|
||||
}
|
||||
// Ignore all other errors from pidfdFind,
|
||||
// as the callers do not expect them, and
|
||||
// we can use pid anyway.
|
||||
return newProcess(pid, h), nil
|
||||
}
|
||||
|
||||
func (p *ProcessState) userTime() time.Duration {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
package os
|
||||
|
||||
import (
|
||||
"internal/godebug"
|
||||
"internal/syscall/unix"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
|
@ -49,6 +50,25 @@ func getPidfd(sysAttr *syscall.SysProcAttr) uintptr {
|
|||
return uintptr(*sysAttr.PidFD)
|
||||
}
|
||||
|
||||
var osfinderr = godebug.New("osfinderr")
|
||||
|
||||
func pidfdFind(pid int) (uintptr, error) {
|
||||
if !pidfdWorks() {
|
||||
return unsetHandle, syscall.ENOSYS
|
||||
}
|
||||
if osfinderr.Value() == "0" {
|
||||
osfinderr.IncNonDefault()
|
||||
return unsetHandle, syscall.ENOSYS
|
||||
|
||||
}
|
||||
|
||||
h, err := unix.PidFDOpen(pid, 0)
|
||||
if err == nil {
|
||||
return h, nil
|
||||
}
|
||||
return unsetHandle, convertESRCH(err)
|
||||
}
|
||||
|
||||
func (p *Process) pidfdRelease() {
|
||||
// Release pidfd unconditionally.
|
||||
handle := p.handle.Swap(unsetHandle)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ func getPidfd(_ *syscall.SysProcAttr) uintptr {
|
|||
return unsetHandle
|
||||
}
|
||||
|
||||
func pidfdFind(_ int) (uintptr, error) {
|
||||
return unsetHandle, syscall.ENOSYS
|
||||
}
|
||||
|
||||
func (p *Process) pidfdRelease() {}
|
||||
|
||||
func (_ *Process) pidfdWait() (*ProcessState, error) {
|
||||
|
|
|
|||
|
|
@ -290,6 +290,10 @@ Below is the full list of supported metrics, ordered lexicographically.
|
|||
The number of non-default behaviors executed by the net package
|
||||
due to a non-default GODEBUG=multipathtcp=... setting.
|
||||
|
||||
/godebug/non-default-behavior/osfinderr:events
|
||||
The number of non-default behaviors executed by the os package
|
||||
due to a non-default GODEBUG=osfinderr=... setting.
|
||||
|
||||
/godebug/non-default-behavior/panicnil:events
|
||||
The number of non-default behaviors executed by the runtime
|
||||
package due to a non-default GODEBUG=panicnil=... setting.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue