bind9/lib/isc/resource.c
Tony Finch 138908b211 Avoid dead code warning when using a constant boolean
The value of `sign_bit` is platform-dependent but constant at compile
time. Use a cast to convert the boolean `sign_bit` to 0 or 1 instead of
ternary `?:` because one branch of the conditional is dead code. (We
could leave out the cast to `size_t` but our style prefers to handle
booleans more explicitly, hence the `?:` that caused the issue.)

    *** CID 358310:  Possible Control flow issues  (DEADCODE)
    /lib/isc/resource.c: 118 in isc_resource_setlimit()
    112     		 * rlim_t, and whether rlim_t has a sign bit.
    113     		 */
    114     		isc_resourcevalue_t rlim_max = UINT64_MAX;
    115     		size_t wider = sizeof(rlim_max) - sizeof(rlim_t);
    116     		bool sign_bit = (double)(rlim_t)-1 < 0;
    117
    >>>     CID 358310:  Possible Control flow issues  (DEADCODE)
    >>>     Execution cannot reach the expression "1" inside this statement: "rlim_max >>= 8UL * wider + ...".
    118     		rlim_max >>= CHAR_BIT * wider + (sign_bit ? 1 : 0);
    119     		rlim_value = ISC_MIN(value, rlim_max);
    120     	}
    121
    122     	rl.rlim_cur = rl.rlim_max = rlim_value;
    123     	unixresult = setrlimit(unixresource, &rl);
2022-10-05 15:51:05 +00:00

208 lines
5.2 KiB
C

/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <inttypes.h>
#include <stdbool.h>
#include <sys/resource.h>
#include <sys/time.h> /* Required on some systems for <sys/resource.h>. */
#include <sys/types.h>
#include <isc/resource.h>
#include <isc/result.h>
#include <isc/util.h>
#ifdef __linux__
#include <linux/fs.h> /* To get the large NR_OPEN. */
#endif /* ifdef __linux__ */
#include "errno2result.h"
static isc_result_t
resource2rlim(isc_resource_t resource, int *rlim_resource) {
isc_result_t result = ISC_R_SUCCESS;
switch (resource) {
case isc_resource_coresize:
*rlim_resource = RLIMIT_CORE;
break;
case isc_resource_cputime:
*rlim_resource = RLIMIT_CPU;
break;
case isc_resource_datasize:
*rlim_resource = RLIMIT_DATA;
break;
case isc_resource_filesize:
*rlim_resource = RLIMIT_FSIZE;
break;
case isc_resource_lockedmemory:
#ifdef RLIMIT_MEMLOCK
*rlim_resource = RLIMIT_MEMLOCK;
#else /* ifdef RLIMIT_MEMLOCK */
result = ISC_R_NOTIMPLEMENTED;
#endif /* ifdef RLIMIT_MEMLOCK */
break;
case isc_resource_openfiles:
#ifdef RLIMIT_NOFILE
*rlim_resource = RLIMIT_NOFILE;
#else /* ifdef RLIMIT_NOFILE */
result = ISC_R_NOTIMPLEMENTED;
#endif /* ifdef RLIMIT_NOFILE */
break;
case isc_resource_processes:
#ifdef RLIMIT_NPROC
*rlim_resource = RLIMIT_NPROC;
#else /* ifdef RLIMIT_NPROC */
result = ISC_R_NOTIMPLEMENTED;
#endif /* ifdef RLIMIT_NPROC */
break;
case isc_resource_residentsize:
#ifdef RLIMIT_RSS
*rlim_resource = RLIMIT_RSS;
#else /* ifdef RLIMIT_RSS */
result = ISC_R_NOTIMPLEMENTED;
#endif /* ifdef RLIMIT_RSS */
break;
case isc_resource_stacksize:
*rlim_resource = RLIMIT_STACK;
break;
default:
/*
* This test is not very robust if isc_resource_t
* changes, but generates a clear assertion message.
*/
REQUIRE(resource >= isc_resource_coresize &&
resource <= isc_resource_stacksize);
result = ISC_R_RANGE;
break;
}
return (result);
}
isc_result_t
isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
struct rlimit rl;
rlim_t rlim_value;
int unixresult;
int unixresource;
isc_result_t result;
result = resource2rlim(resource, &unixresource);
if (result != ISC_R_SUCCESS) {
return (result);
}
if (value == ISC_RESOURCE_UNLIMITED) {
rlim_value = RLIM_INFINITY;
} else {
/*
* Carefully ensure the range of rlim_t is not overflowed, by
* calculating how many bytes wider is isc_resourcevalue_t than
* rlim_t, and whether rlim_t has a sign bit.
*/
isc_resourcevalue_t rlim_max = UINT64_MAX;
size_t wider = sizeof(rlim_max) - sizeof(rlim_t);
size_t sign_bit = (size_t)(0.0 > (double)(rlim_t)-1);
rlim_max >>= CHAR_BIT * wider + sign_bit;
rlim_value = ISC_MIN(value, rlim_max);
}
rl.rlim_cur = rl.rlim_max = rlim_value;
unixresult = setrlimit(unixresource, &rl);
if (unixresult == 0) {
return (ISC_R_SUCCESS);
}
#if defined(OPEN_MAX) && defined(__APPLE__)
/*
* The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
* maximum possible value is OPEN_MAX. BIND8 used to use
* sysconf(_SC_OPEN_MAX) for such a case, but this value is much
* smaller than OPEN_MAX and is not really effective.
*/
if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
rl.rlim_cur = OPEN_MAX;
unixresult = setrlimit(unixresource, &rl);
if (unixresult == 0) {
return (ISC_R_SUCCESS);
}
}
#elif defined(__linux__)
#ifndef NR_OPEN
#define NR_OPEN (1024 * 1024)
#endif /* ifndef NR_OPEN */
/*
* Some Linux kernels don't accept RLIM_INFINIT; the maximum
* possible value is the NR_OPEN defined in linux/fs.h.
*/
if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
rl.rlim_cur = rl.rlim_max = NR_OPEN;
unixresult = setrlimit(unixresource, &rl);
if (unixresult == 0) {
return (ISC_R_SUCCESS);
}
}
#endif /* if defined(OPEN_MAX) && defined(__APPLE__) */
if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
if (getrlimit(unixresource, &rl) == 0) {
rl.rlim_cur = rl.rlim_max;
unixresult = setrlimit(unixresource, &rl);
if (unixresult == 0) {
return (ISC_R_SUCCESS);
}
}
}
return (isc__errno2result(errno));
}
isc_result_t
isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
int unixresource;
struct rlimit rl;
isc_result_t result;
result = resource2rlim(resource, &unixresource);
if (result != ISC_R_SUCCESS) {
return (result);
}
if (getrlimit(unixresource, &rl) != 0) {
return (isc__errno2result(errno));
}
*value = rl.rlim_max;
return (ISC_R_SUCCESS);
}
isc_result_t
isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
int unixresource;
struct rlimit rl;
isc_result_t result;
result = resource2rlim(resource, &unixresource);
if (result != ISC_R_SUCCESS) {
return (result);
}
if (getrlimit(unixresource, &rl) != 0) {
return (isc__errno2result(errno));
}
*value = rl.rlim_cur;
return (ISC_R_SUCCESS);
}