Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isc / unix / resource.c
blob2bdcdd1ba43816e75039f8870d24d2da9916d7fc
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.11.2.1 2004/03/09 06:12:11 marka Exp $ */
20 #include <config.h>
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>
29 #include <isc/util.h>
31 #include "errno2result.h"
33 static isc_result_t
34 resource2rlim(isc_resource_t resource, int *rlim_resource) {
35 isc_result_t result = ISC_R_SUCCESS;
37 switch (resource) {
38 case isc_resource_coresize:
39 *rlim_resource = RLIMIT_CORE;
40 break;
41 case isc_resource_cputime:
42 *rlim_resource = RLIMIT_CPU;
43 break;
44 case isc_resource_datasize:
45 *rlim_resource = RLIMIT_DATA;
46 break;
47 case isc_resource_filesize:
48 *rlim_resource = RLIMIT_FSIZE;
49 break;
50 case isc_resource_lockedmemory:
51 #ifdef RLIMIT_MEMLOCK
52 *rlim_resource = RLIMIT_MEMLOCK;
53 #else
54 result = ISC_R_NOTIMPLEMENTED;
55 #endif
56 break;
57 case isc_resource_openfiles:
58 #ifdef RLIMIT_NOFILE
59 *rlim_resource = RLIMIT_NOFILE;
60 #else
61 result = ISC_R_NOTIMPLEMENTED;
62 #endif
63 break;
64 case isc_resource_processes:
65 #ifdef RLIMIT_NPROC
66 *rlim_resource = RLIMIT_NPROC;
67 #else
68 result = ISC_R_NOTIMPLEMENTED;
69 #endif
70 break;
71 case isc_resource_residentsize:
72 #ifdef RLIMIT_RSS
73 *rlim_resource = RLIMIT_RSS;
74 #else
75 result = ISC_R_NOTIMPLEMENTED;
76 #endif
77 break;
78 case isc_resource_stacksize:
79 *rlim_resource = RLIMIT_STACK;
80 break;
81 default:
83 * This test is not very robust if isc_resource_t
84 * changes, but generates a clear assertion message.
86 REQUIRE(resource >= isc_resource_coresize &&
87 resource <= isc_resource_stacksize);
89 result = ISC_R_RANGE;
90 break;
93 return (result);
96 isc_result_t
97 isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
98 struct rlimit rl;
99 ISC_PLATFORM_RLIMITTYPE rlim_value;
100 int unixresult;
101 int unixresource;
102 isc_result_t result;
104 result = resource2rlim(resource, &unixresource);
105 if (result != ISC_R_SUCCESS)
106 return (result);
108 if (value == ISC_RESOURCE_UNLIMITED)
109 rlim_value = RLIM_INFINITY;
111 else {
113 * isc_resourcevalue_t was chosen as an unsigned 64 bit
114 * integer so that it could contain the maximum range of
115 * reasonable values. Unfortunately, this exceeds the typical
116 * range on Unix systems. Ensure the range of
117 * ISC_PLATFORM_RLIMITTYPE is not overflowed.
119 isc_resourcevalue_t rlim_max;
120 isc_boolean_t rlim_t_is_signed =
121 ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
123 if (rlim_t_is_signed)
124 rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
125 (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
126 else
127 rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
129 if (value > rlim_max)
130 value = rlim_max;
132 rlim_value = value;
136 * The BIND 8 documentation reports:
138 * Note: on some operating systems the server cannot set an
139 * unlimited value and cannot determine the maximum number of
140 * open files the kernel can support. On such systems, choosing
141 * unlimited will cause the server to use the larger of the
142 * rlim_max for RLIMIT_NOFILE and the value returned by
143 * sysconf(_SC_OPEN_MAX). If the actual kernel limit is larger
144 * than this value, use limit files to specify the limit
145 * explicitly.
147 * The CHANGES for 8.1.2-T3A also mention:
149 * 352. [bug] Because of problems with setting an infinite
150 * rlim_max for RLIMIT_NOFILE on some systems, previous versions
151 * of the server implemented "limit files unlimited" by setting
152 * the limit to the value returned by sysconf(_SC_OPEN_MAX). The
153 * server will now use RLIM_INFINITY on systems which allow it.
155 * At some point the BIND 8 server stopped using SC_OPEN_MAX for this
156 * purpose at all, but it isn't clear to me when or why, as my access
157 * to the CVS archive is limited at the time of this writing. What
158 * BIND 8 *does* do is to set RLIMIT_NOFILE to either RLIMIT_INFINITY
159 * on a half dozen operating systems or to FD_SETSIZE on the rest,
160 * the latter of which is probably fewer than the real limit. (Note
161 * that libisc's socket module will have problems with any fd over
162 * FD_SETSIZE. This should be fixed in the socket module, not a
163 * limitation here. BIND 8's eventlib also has a problem, making
164 * its RLIMIT_INFINITY setting useless, because it closes and ignores
165 * any fd over FD_SETSIZE.)
167 * More troubling is the reference to some operating systems not being
168 * able to set an unlimited value for the number of open files. I'd
169 * hate to put in code that is really only there to support archaic
170 * systems that the rest of libisc won't work on anyway. So what this
171 * extremely verbose comment is here to say is the following:
173 * I'm aware there might be an issue with not limiting the value
174 * for RLIMIT_NOFILE on some systems, but since I don't know yet
175 * what those systems are and what the best workaround is (use
176 * sysconf()? rlim_max from getrlimit()? FD_SETSIZE?) so nothing
177 * is currently being done to clamp the value for open files.
180 rl.rlim_cur = rl.rlim_max = rlim_value;
181 unixresult = setrlimit(unixresource, &rl);
183 if (unixresult == 0)
184 return (ISC_R_SUCCESS);
185 else
186 return (isc__errno2result(errno));
189 isc_result_t
190 isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
191 int unixresult;
192 int unixresource;
193 struct rlimit rl;
194 isc_result_t result;
196 result = resource2rlim(resource, &unixresource);
197 if (result == ISC_R_SUCCESS) {
198 unixresult = getrlimit(unixresource, &rl);
199 INSIST(unixresult == 0);
200 *value = rl.rlim_max;
203 return (result);