Skip to content

Commit

Permalink
unix: retry fetching of lists through sysctl if the size changes
Browse files Browse the repository at this point in the history
On macOS, the SysctlKinfoProcSlice() function may be used to fetch the
contents of the process table. As the process table may grow between the
first and second call to sysctl(), the second call may fail with ENOMEM.
In that case we simply need to retry.
  • Loading branch information
EdSchouten committed Jul 25, 2023
1 parent ad7130c commit d319d1b
Showing 1 changed file with 28 additions and 22 deletions.
50 changes: 28 additions & 22 deletions unix/syscall_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,30 +510,36 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
return nil, err
}

// Find size.
n := uintptr(0)
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
return nil, err
}
if n == 0 {
return nil, nil
}
if n%SizeofKinfoProc != 0 {
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
}
for {
// Find size.
n := uintptr(0)
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
return nil, err
}
if n == 0 {
return nil, nil
}
if n%SizeofKinfoProc != 0 {
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
}

// Read into buffer of that size.
buf := make([]KinfoProc, n/SizeofKinfoProc)
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil {
return nil, err
}
if n%SizeofKinfoProc != 0 {
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
}
// Read into buffer of that size. Retry if ENOMEM is
// returned, as it indicates the process table grew in
// the meantime.
buf := make([]KinfoProc, n/SizeofKinfoProc)
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != ENOMEM {
if err != nil {
return nil, err
}
if n%SizeofKinfoProc != 0 {
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
}

// The actual call may return less than the original reported required
// size so ensure we deal with that.
return buf[:n/SizeofKinfoProc], nil
// The actual call may return less than the original reported required
// size so ensure we deal with that.
return buf[:n/SizeofKinfoProc], nil
}
}
}

//sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)
Expand Down

0 comments on commit d319d1b

Please sign in to comment.