2 * Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: resource.c,v 1.12.944.4 2008/07/28 22:44:46 marka Exp $ */
22 #include <sys/types.h>
23 #include <sys/time.h> /* Required on some systems for <sys/resource.h>. */
24 #include <sys/resource.h>
26 #include <isc/platform.h>
27 #include <isc/resource.h>
28 #include <isc/result.h>
32 #include <linux/fs.h> /* To get the large NR_OPEN. */
36 #include <sys/dyntune.h>
39 #include "errno2result.h"
42 resource2rlim(isc_resource_t resource, int *rlim_resource) {
43 isc_result_t result = ISC_R_SUCCESS;
46 case isc_resource_coresize:
47 *rlim_resource = RLIMIT_CORE;
49 case isc_resource_cputime:
50 *rlim_resource = RLIMIT_CPU;
52 case isc_resource_datasize:
53 *rlim_resource = RLIMIT_DATA;
55 case isc_resource_filesize:
56 *rlim_resource = RLIMIT_FSIZE;
58 case isc_resource_lockedmemory:
60 *rlim_resource = RLIMIT_MEMLOCK;
62 result = ISC_R_NOTIMPLEMENTED;
65 case isc_resource_openfiles:
67 *rlim_resource = RLIMIT_NOFILE;
69 result = ISC_R_NOTIMPLEMENTED;
72 case isc_resource_processes:
74 *rlim_resource = RLIMIT_NPROC;
76 result = ISC_R_NOTIMPLEMENTED;
79 case isc_resource_residentsize:
81 *rlim_resource = RLIMIT_RSS;
83 result = ISC_R_NOTIMPLEMENTED;
86 case isc_resource_stacksize:
87 *rlim_resource = RLIMIT_STACK;
91 * This test is not very robust if isc_resource_t
92 * changes, but generates a clear assertion message.
94 REQUIRE(resource >= isc_resource_coresize &&
95 resource <= isc_resource_stacksize);
105 isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
107 ISC_PLATFORM_RLIMITTYPE rlim_value;
112 result = resource2rlim(resource, &unixresource);
113 if (result != ISC_R_SUCCESS)
116 if (value == ISC_RESOURCE_UNLIMITED)
117 rlim_value = RLIM_INFINITY;
121 * isc_resourcevalue_t was chosen as an unsigned 64 bit
122 * integer so that it could contain the maximum range of
123 * reasonable values. Unfortunately, this exceeds the typical
124 * range on Unix systems. Ensure the range of
125 * ISC_PLATFORM_RLIMITTYPE is not overflowed.
127 isc_resourcevalue_t rlim_max;
128 isc_boolean_t rlim_t_is_signed =
129 ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
131 if (rlim_t_is_signed)
132 rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
133 (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
135 rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
137 if (value > rlim_max)
144 * The BIND 8 documentation reports:
146 * Note: on some operating systems the server cannot set an
147 * unlimited value and cannot determine the maximum number of
148 * open files the kernel can support. On such systems, choosing
149 * unlimited will cause the server to use the larger of the
150 * rlim_max for RLIMIT_NOFILE and the value returned by
151 * sysconf(_SC_OPEN_MAX). If the actual kernel limit is larger
152 * than this value, use limit files to specify the limit
155 * The CHANGES for 8.1.2-T3A also mention:
157 * 352. [bug] Because of problems with setting an infinite
158 * rlim_max for RLIMIT_NOFILE on some systems, previous versions
159 * of the server implemented "limit files unlimited" by setting
160 * the limit to the value returned by sysconf(_SC_OPEN_MAX). The
161 * server will now use RLIM_INFINITY on systems which allow it.
163 * At some point the BIND 8 server stopped using SC_OPEN_MAX for this
164 * purpose at all, but it isn't clear to me when or why, as my access
165 * to the CVS archive is limited at the time of this writing. What
166 * BIND 8 *does* do is to set RLIMIT_NOFILE to either RLIMIT_INFINITY
167 * on a half dozen operating systems or to FD_SETSIZE on the rest,
168 * the latter of which is probably fewer than the real limit. (Note
169 * that libisc's socket module will have problems with any fd over
170 * FD_SETSIZE. This should be fixed in the socket module, not a
171 * limitation here. BIND 8's eventlib also has a problem, making
172 * its RLIMIT_INFINITY setting useless, because it closes and ignores
173 * any fd over FD_SETSIZE.)
175 * More troubling is the reference to some operating systems not being
176 * able to set an unlimited value for the number of open files. I'd
177 * hate to put in code that is really only there to support archaic
178 * systems that the rest of libisc won't work on anyway. So what this
179 * extremely verbose comment is here to say is the following:
181 * I'm aware there might be an issue with not limiting the value
182 * for RLIMIT_NOFILE on some systems, but since I don't know yet
183 * what those systems are and what the best workaround is (use
184 * sysconf()? rlim_max from getrlimit()? FD_SETSIZE?) so nothing
185 * is currently being done to clamp the value for open files.
188 rl.rlim_cur = rl.rlim_max = rlim_value;
189 unixresult = setrlimit(unixresource, &rl);
192 return (ISC_R_SUCCESS);
194 #if defined(OPEN_MAX) && defined(__APPLE__)
196 * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
197 * maximum possible value is OPEN_MAX. BIND8 used to use
198 * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
199 * smaller than OPEN_MAX and is not really effective.
201 if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
202 rl.rlim_cur = OPEN_MAX;
203 unixresult = setrlimit(unixresource, &rl);
205 return (ISC_R_SUCCESS);
207 #elif defined(NR_OPEN) && defined(__linux__)
209 * Some Linux kernels don't accept RLIM_INFINIT; the maximum
210 * possible value is the NR_OPEN defined in linux/fs.h.
212 if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
213 rl.rlim_cur = rl.rlim_max = NR_OPEN;
214 unixresult = setrlimit(unixresource, &rl);
216 return (ISC_R_SUCCESS);
218 #elif defined(__hpux)
219 if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
221 if (gettune("maxfiles_lim", &maxfiles) == 0) {
222 rl.rlim_cur = rl.rlim_max = maxfiles;
223 unixresult = setrlimit(unixresource, &rl);
225 return (ISC_R_SUCCESS);
229 if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
230 if (getrlimit(unixresource, &rl) == 0) {
231 rl.rlim_cur = rl.rlim_max;
232 unixresult = setrlimit(unixresource, &rl);
234 return (ISC_R_SUCCESS);
237 return (isc__errno2result(errno));
241 isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
247 result = resource2rlim(resource, &unixresource);
248 if (result == ISC_R_SUCCESS) {
249 unixresult = getrlimit(unixresource, &rl);
250 INSIST(unixresult == 0);
251 *value = rl.rlim_max;
258 isc_resource_curlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
264 result = resource2rlim(resource, &unixresource);
265 if (result == ISC_R_SUCCESS) {
266 unixresult = getrlimit(unixresource, &rl);
267 INSIST(unixresult == 0);
268 *value = rl.rlim_cur;