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  }