/* * Copyright (C) 2000 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* $Id: resource.c,v 1.1 2000/11/14 23:38:10 tale Exp $ */ #include #include #include #include #include #include "errno2result.h" static int resource2rlim(isc_resource_t resource) { switch (resource) { case isc_resource_coresize: return (RLIMIT_CORE); case isc_resource_cputime: return (RLIMIT_CPU); case isc_resource_datasize: return (RLIMIT_DATA); case isc_resource_filesize: return (RLIMIT_FSIZE); case isc_resource_lockedmemory: return (RLIMIT_MEMLOCK); case isc_resource_openfiles: return (RLIMIT_NOFILE); case isc_resource_processes: return (RLIMIT_NPROC); case isc_resource_residentsize: return (RLIMIT_RSS); case isc_resource_stacksize: return (RLIMIT_STACK); 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); /* * This return value is not really meant to be checked * by the caller, as the contract for the public functions * is that 'resource' be a member of the enumeration. */ return (-1); } } 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; unixresource = resource2rlim(resource); 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 value of rlim_t is not * overflowed. */ isc_resourcevalue_t rlim_max; isc_boolean_t rlim_t_is_signed = ISC_TF(((double)(rlim_t)-1) < 0); if (rlim_t_is_signed) rlim_max = ~((rlim_t)1 << (sizeof(rlim_t) * 8 - 1)); else rlim_max = (rlim_t)-1; if (value > rlim_max) value = rlim_max; rlim_value = value; } /* * The BIND 8 documentation reports: * * Note: on some operating systems the server cannot set an * unlimited value and cannot determine the maximum number of * open files the kernel can support. On such systems, choosing * unlimited will cause the server to use the larger of the * rlim_max for RLIMIT_NOFILE and the value returned by * sysconf(_SC_OPEN_MAX). If the actual kernel limit is larger * than this value, use limit files to specify the limit * explicitly. * * The CHANGES for 8.1.2-T3A also mention: * * 352. [bug] Because of problems with setting an infinite * rlim_max for RLIMIT_NOFILE on some systems, previous versions * of the server implemented "limit files unlimited" by setting * the limit to the value returned by sysconf(_SC_OPEN_MAX). The * server will now use RLIM_INFINITY on systems which allow it. * * At some point the BIND 8 server stopped using SC_OPEN_MAX for this * purpose at all, but it isn't clear to me when or why, as my access * to the CVS archive is limited at the time of this writing. What * BIND 8 *does* do is to set RLIMIT_NOFILE to either RLIMIT_INFINITY * on a half dozen operating systems or to FD_SETSIZE on the rest, * the latter of which is probably fewer than the real limit. (Note * that libisc's socket module will have problems with any fd over * FD_SETSIZE. This should be fixed in the socket module, not a * limitation here. BIND 8's eventlib also has a problem, making * its RLIMIT_INFINITY setting useless, because it closes and ignores * any fd over FD_SETSIZE.) * * More troubling is the reference to some operating systems not being * able to set an unlimited value for the number of open files. I'd * hate to put in code that is really only there to support archaic * systems that the rest of libisc won't work on anyway. So what this * extremely verbose comment is here to say is the following: * * I'm aware there might be an issue with not limiting the value * for RLIMIT_NOFILE on some systems, but since I don't know yet * what those systems are and what the best workaround is (use * sysconf()? rlim_max from getrlimit()? FD_SETSIZE?) so nothing * is currently being done to clamp the value for open files. */ rl.rlim_cur = rl.rlim_max = rlim_value; unixresult = setrlimit(unixresource, &rl); if (unixresult == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); } isc_resourcevalue_t isc_resource_getlimit(isc_resource_t resource) { int unixresult; int unixresource; struct rlimit rl; unixresource = resource2rlim(resource); unixresult = getrlimit(unixresource, &rl); INSIST(unixresult == 0); return (rl.rlim_max); }