Skip to content

Commit cdea1ad

Browse files
committed
unix: retry fetching of lists through sysctl if the size changes
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.
1 parent ad7130c commit cdea1ad

File tree

1 file changed

+28
-22
lines changed

1 file changed

+28
-22
lines changed

unix/syscall_darwin.go

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -510,30 +510,36 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
510510
return nil, err
511511
}
512512

513-
// Find size.
514-
n := uintptr(0)
515-
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
516-
return nil, err
517-
}
518-
if n == 0 {
519-
return nil, nil
520-
}
521-
if n%SizeofKinfoProc != 0 {
522-
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
523-
}
513+
for {
514+
// Find size.
515+
n := uintptr(0)
516+
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
517+
return nil, err
518+
}
519+
if n == 0 {
520+
return nil, nil
521+
}
522+
if n%SizeofKinfoProc != 0 {
523+
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
524+
}
524525

525-
// Read into buffer of that size.
526-
buf := make([]KinfoProc, n/SizeofKinfoProc)
527-
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil {
528-
return nil, err
529-
}
530-
if n%SizeofKinfoProc != 0 {
531-
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
532-
}
526+
// Read into buffer of that size. Retry if ENOMEM is
527+
// returneds, as it indicates the process table grew in
528+
// the meantime.
529+
buf := make([]KinfoProc, n/SizeofKinfoProc)
530+
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != ENOMEM {
531+
if err != nil {
532+
return nil, err
533+
}
534+
if n%SizeofKinfoProc != 0 {
535+
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
536+
}
533537

534-
// The actual call may return less than the original reported required
535-
// size so ensure we deal with that.
536-
return buf[:n/SizeofKinfoProc], nil
538+
// The actual call may return less than the original reported required
539+
// size so ensure we deal with that.
540+
return buf[:n/SizeofKinfoProc], nil
541+
}
542+
}
537543
}
538544

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

0 commit comments

Comments
 (0)