summaryrefslogtreecommitdiffstats
path: root/lib/isc/unix/resource.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/isc/unix/resource.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/lib/isc/unix/resource.c b/lib/isc/unix/resource.c
new file mode 100644
index 0000000..6d5c5aa
--- /dev/null
+++ b/lib/isc/unix/resource.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <sys/types.h>
+#include <sys/time.h> /* Required on some systems for <sys/resource.h>. */
+#include <sys/resource.h>
+
+#include <isc/platform.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
+
+#if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
+#include <sys/dyntune.h>
+#endif
+
+#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
+ result = ISC_R_NOTIMPLEMENTED;
+#endif
+ break;
+ case isc_resource_openfiles:
+#ifdef RLIMIT_NOFILE
+ *rlim_resource = RLIMIT_NOFILE;
+#else
+ result = ISC_R_NOTIMPLEMENTED;
+#endif
+ break;
+ case isc_resource_processes:
+#ifdef RLIMIT_NPROC
+ *rlim_resource = RLIMIT_NPROC;
+#else
+ result = ISC_R_NOTIMPLEMENTED;
+#endif
+ break;
+ case isc_resource_residentsize:
+#ifdef RLIMIT_RSS
+ *rlim_resource = RLIMIT_RSS;
+#else
+ result = ISC_R_NOTIMPLEMENTED;
+#endif
+ 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;
+ ISC_PLATFORM_RLIMITTYPE 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 {
+ /*
+ * isc_resourcevalue_t was chosen as an unsigned 64 bit
+ * integer so that it could contain the maximum range of
+ * reasonable values. Unfortunately, this exceeds the typical
+ * range on Unix systems. Ensure the range of
+ * ISC_PLATFORM_RLIMITTYPE is not overflowed.
+ */
+ isc_resourcevalue_t rlim_max;
+ bool rlim_t_is_signed =
+ (((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
+
+ if (rlim_t_is_signed)
+ rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
+ (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
+ else
+ rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
+
+ if (value > rlim_max)
+ value = rlim_max;
+
+ rlim_value = value;
+ }
+
+ 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
+
+ /*
+ * 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);
+ }
+#elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
+ if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+ uint64_t maxfiles;
+ if (gettune("maxfiles_lim", &maxfiles) == 0) {
+ rl.rlim_cur = rl.rlim_max = maxfiles;
+ unixresult = setrlimit(unixresource, &rl);
+ if (unixresult == 0)
+ return (ISC_R_SUCCESS);
+ }
+ }
+#endif
+ 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 unixresult;
+ int unixresource;
+ struct rlimit rl;
+ isc_result_t result;
+
+ result = resource2rlim(resource, &unixresource);
+ if (result == ISC_R_SUCCESS) {
+ unixresult = getrlimit(unixresource, &rl);
+ INSIST(unixresult == 0);
+ *value = rl.rlim_max;
+ }
+
+ return (result);
+}
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+ int unixresult;
+ int unixresource;
+ struct rlimit rl;
+ isc_result_t result;
+
+ result = resource2rlim(resource, &unixresource);
+ if (result == ISC_R_SUCCESS) {
+ unixresult = getrlimit(unixresource, &rl);
+ INSIST(unixresult == 0);
+ *value = rl.rlim_cur;
+ }
+
+ return (result);
+}