-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Description
We've noticed a while back that when setting the file descriptor allowance on macos, Go restricts it to a lower value than requested:
package main
import (
"fmt"
"syscall"
)
func main() {
// Get the current file descriptor limit
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
panic(err)
}
// Try to update the limit to the max allowance
limit.Cur = limit.Max
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
panic(err)
}
// Try to get the limit again and see where it's at
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
panic(err)
}
fmt.Println(limit.Cur)
}The above code on Linux works as expected, setting the limit to the max returned by the syscall package.
On macos with Go 1.11.5 (and prior) it silently set it to the minimum of limit.Max and 10240. We had to patch our code to explicitly check the actual value set instead of relying on no-error-returned since we falsely alloted more fds to databases than available.
On macos with Go 1.12, our code again started to blow up, now returning invalid argument errors instead of the silent capping previously.
I'd probably say both behaviors are bad, but the new one is a lot worse than the previous. Now it only tells us it's invalid, but unless you know the magic number defined in the your own kernel version, there's no way for user code to figure out how many fds are actually available.