diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in index 843cf1c66f..a16b8e17ac 100644 --- a/lib/isc/unix/Makefile.in +++ b/lib/isc/unix/Makefile.in @@ -13,7 +13,7 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.32 2000/08/29 18:23:59 bwelling Exp $ +# $Id: Makefile.in,v 1.33 2000/11/14 23:38:09 tale Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -32,13 +32,13 @@ CWARNINGS = OBJS = @ISC_IPV6_O@ \ app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \ fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \ - os.@O@ socket.@O@ stdio.@O@ stdtime.@O@ time.@O@ + os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ time.@O@ # Alphabetically SRCS = @ISC_IPV6_C@ \ app.c dir.c entropy.c errno2result.c file.c \ fsaccess.c interfaceiter.c keyboard.c net.c \ - os.c socket.c stdio.c stdtime.c time.c + os.c resource.c socket.c stdio.c stdtime.c time.c SUBDIRS = include TARGETS = ${OBJS} diff --git a/lib/isc/unix/resource.c b/lib/isc/unix/resource.c new file mode 100644 index 0000000000..de66418233 --- /dev/null +++ b/lib/isc/unix/resource.c @@ -0,0 +1,167 @@ +/* + * 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); +}