github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/server/rlimit_darwin.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 // +build !windows,!freebsd,!dragonfly 12 13 package server 14 15 import ( 16 "unsafe" 17 18 "golang.org/x/sys/unix" 19 ) 20 21 // #include <sys/types.h> 22 // #include <sys/sysctl.h> 23 import "C" 24 25 func setRlimitNoFile(limits *rlimit) error { 26 return unix.Setrlimit(unix.RLIMIT_NOFILE, (*unix.Rlimit)(limits)) 27 } 28 29 func getRlimitNoFile(limits *rlimit) error { 30 if err := unix.Getrlimit(unix.RLIMIT_NOFILE, (*unix.Rlimit)(limits)); err != nil { 31 return err 32 } 33 // On macOS, the true hard open file limit is 34 // min(sysctl("kern.maxfiles"), 35 // sysctl("kern.maxfilesperproc"), 36 // getrlimit(RLIMIT_NOFILE)) 37 // This does not appear to be documented and may be incomplete. 38 // 39 // See https://github.com/golang/go/issues/30401 for more context. 40 sysctlMaxFiles, err := getSysctlMaxFiles() 41 if err != nil { 42 return err 43 } 44 if limits.Max > sysctlMaxFiles { 45 limits.Max = sysctlMaxFiles 46 } 47 sysctlMaxFilesPerProc, err := getSysctlMaxFilesPerProc() 48 if err != nil { 49 return err 50 } 51 if limits.Max > sysctlMaxFilesPerProc { 52 limits.Max = sysctlMaxFilesPerProc 53 } 54 return nil 55 } 56 57 func getSysctlMaxFiles() (uint64, error) { 58 return getSysctl(C.CTL_KERN, C.KERN_MAXFILES) // identifies the "kern.maxfiles" sysctl 59 } 60 61 func getSysctlMaxFilesPerProc() (uint64, error) { 62 return getSysctl(C.CTL_KERN, C.KERN_MAXFILESPERPROC) // identifies the "kern.maxfilesperproc" sysctl 63 } 64 65 func getSysctl(x, y C.int) (uint64, error) { 66 var out int32 67 outLen := C.size_t(unsafe.Sizeof(out)) 68 sysctlMib := [...]C.int{x, y} 69 r, errno := C.sysctl(&sysctlMib[0], C.u_int(len(sysctlMib)), unsafe.Pointer(&out), &outLen, 70 nil /* newp */, 0 /* newlen */) 71 if r != 0 { 72 return 0, errno 73 } 74 return uint64(out), nil 75 }