...

Source file src/github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/limits/limits.go

Documentation: github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/limits

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // +build !windows,!freebsd
    16  
    17  // Package limits provides routines to check and enforce certain resource
    18  // limits on the Cloud SQL client proxy process.
    19  package limits
    20  
    21  import (
    22  	"fmt"
    23  	"syscall"
    24  
    25  	"github.com/GoogleCloudPlatform/cloudsql-proxy/logging"
    26  )
    27  
    28  var (
    29  	// For overriding in unittests.
    30  	syscallGetrlimit = syscall.Getrlimit
    31  	syscallSetrlimit = syscall.Setrlimit
    32  )
    33  
    34  // Each connection handled by the proxy requires two file descriptors, one
    35  // for the local end of the connection and one for the remote. So, the proxy
    36  // process should be able to open at least 8K file descriptors if it is to
    37  // handle 4K connections to one instance.
    38  const ExpectedFDs = 8500
    39  
    40  // SetupFDLimits ensures that the process running the Cloud SQL proxy can have
    41  // at least wantFDs number of open file descriptors. It returns an error if it
    42  // cannot ensure the same.
    43  func SetupFDLimits(wantFDs uint64) error {
    44  	rlim := &syscall.Rlimit{}
    45  	if err := syscallGetrlimit(syscall.RLIMIT_NOFILE, rlim); err != nil {
    46  		return fmt.Errorf("failed to read rlimit for max file descriptors: %v", err)
    47  	}
    48  
    49  	if rlim.Cur >= wantFDs {
    50  		logging.Verbosef("current FDs rlimit set to %d, wanted limit is %d. Nothing to do here.", rlim.Cur, wantFDs)
    51  		return nil
    52  	}
    53  
    54  	// Linux man page:
    55  	// The soft limit is the value that the kernel enforces for the correā€
    56  	// sponding resource. The hard limit acts as a ceiling for the soft limit:
    57  	// an unprivileged process may set only its soft limit to a value in the
    58  	// range from 0 up to the hard limit, and (irreversibly) lower its hard
    59  	// limit. A privileged process (under Linux: one with the CAP_SYS_RESOURCE
    60  	// capability in the initial user namespace) may make arbitrary changes to
    61  	// either limit value.
    62  	if rlim.Max < wantFDs {
    63  		// When the hard limit is less than what is requested, let's just give it a
    64  		// shot, and if we fail, we fallback and try just setting the softlimit.
    65  		rlim2 := &syscall.Rlimit{}
    66  		rlim2.Max = wantFDs
    67  		rlim2.Cur = wantFDs
    68  		if err := syscallSetrlimit(syscall.RLIMIT_NOFILE, rlim2); err == nil {
    69  			logging.Verbosef("Rlimits for file descriptors set to {Current = %v, Max = %v}", rlim2.Cur, rlim2.Max)
    70  			return nil
    71  		}
    72  	}
    73  
    74  	rlim.Cur = wantFDs
    75  	if err := syscallSetrlimit(syscall.RLIMIT_NOFILE, rlim); err != nil {
    76  		return fmt.Errorf(
    77  			`failed to set rlimit {Current = %v, Max = %v} for max file
    78  descriptors. The hard limit on file descriptors (4096) is lower than the
    79  requested rlimit. The proxy will only be able to handle ~2048
    80  connections. To hide this message, please request a limit within the available range.`,
    81  			rlim.Cur,
    82  			rlim.Max,
    83  		)
    84  	}
    85  
    86  	logging.Verbosef("Rlimits for file descriptors set to {Current = %v, Max = %v}", rlim.Cur, rlim.Max)
    87  	return nil
    88  }
    89  

View as plain text