Skip to content

Commit 70f4e40

Browse files
EdSchoutengopherbot
authored andcommitted
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. Change-Id: I40229653ed383603c33762f37b0dc2e7de47bcb6 GitHub-Last-Rev: b63b6b8 GitHub-Pull-Request: #169 Reviewed-on: https://go-review.googlesource.com/c/sys/+/513036 Run-TryBot: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent ad7130c commit 70f4e40

File tree

1 file changed

+28
-22
lines changed

1 file changed

+28
-22
lines changed

unix/syscall_darwin.go

+28-22
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.
527+
buf := make([]KinfoProc, n/SizeofKinfoProc)
528+
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil {
529+
if err == ENOMEM {
530+
// Process table grew. Try again.
531+
continue
532+
}
533+
return nil, err
534+
}
535+
if n%SizeofKinfoProc != 0 {
536+
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
537+
}
533538

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
539+
// The actual call may return less than the original reported required
540+
// size so ensure we deal with that.
541+
return buf[:n/SizeofKinfoProc], nil
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)