Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Sep 1996 20:24:34 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        hackers@FreeBSD.ORG, mark@quickweb.com
Subject:   Re: OPEN_MAX => which #define counts?
Message-ID:  <199609271024.UAA19546@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>Hi, I was poking around /usr/src/sys wondering about OPEN_MAX ... I'm just
>learning about file descriptors and such and I figured out that OPEN_MAX
>determines the max num. of files a process can open.

OPEN_MAX is POSIX run-time invariant (possibly indeterminate) value that
gives the maximum number of files that one process can have open at any
given time.  OPEN_MAX is defined, if at all, in <limits.h>.  Of course,
it may be defined in a header included by <limits.h>.  In FreeBSD,
it is defined in <sys/syslimits.h>.

OPEN_MAX is supposed to be defined if and only if the limit is known
at compile time.  In FreeBSD, the limit isn't known at compile time,
since it can be changed using setrlimit(2) or sysctl(2 or 8) (at
least in 2.1.5R - kern.maxfilesperproc is read-only in current), or
someone may have compiled the kernel with the bogus option OPEN_MAX
so that even the default limit doesn't match the one advertized in
<limits.h>.  This is broken in FreeBSD - OPEN_MAX is defined.

The actual runtime limit is given runtime by sysconf(_SC_OPEN_MAX).
This is supposed to give a value that does not change across process
lifetimes (see /usr/src/lib/libc/sysconf.c).  This requirement is
fundamentally incompatible with the ability of setrlimit() and sysctl()
to change the limit.  I think the problem isn't serious for setrlimit().
POSIX applications can't use setrlimit(), and applications that use it
they can easily keep track of what they change.  There are more serious
problems for sysctl().  Processes don't get notified of the change.
There are implementation bugs that prevent limit from being detected
using sysconf() or getrlimit().  It can be detected using setrlimit()
to set the limit claimed by getrlimit().

>My question is that which #define actually sets the limit:
>
>./conf/options:OPEN_MAX opt_rlimit.h  ---> which contains nothing..
>./i386/conf/LINT:options                OPEN_MAX=128
>./sys/syslimits.h:#define       OPEN_MAX                   64 

None of the above :-).

The limit is:

	min(sysctl variable kern.maxfilesperproc,
	    sysctl variable kern.maxfiles,	/* this should be bigger than
	    					 * the min of the others or
						 * you'll hit the system
						 * limit before the per-process
						 * limit */
	    soft rlimit for the number of files per process)

The soft rlimit is set to NOFILES for the initial process and is inherited
across forks.  NOFILES is defined as OPEN_MAX in <sys/param.h>.  (This is
also bogus.  First, OPEN_MAX should not be defined.  Second, NOFILES is a
pre-POSIX version of OPEN_MAX, so it probably shouldn't be defined either.
In the kernel, it just gives the initial value for the rlimit, and using
it in applications just gives programs that can't handle changes of the
rlimit.)  OPEN_MAX is defined as 64 in <sys/syslimits.h>, unless it is
already defined.  If you use option OPEN_MAX, then OPEN_MAX should be
defined in opt_rlimit.h.  opt_rlimit.h is included in init_main.c before
<sys/param.h> is included.  <sys/param.h> includes <sys/syslimits.h>.
This overrides the default for the soft rlimit.

>The other question I have is how OPEN_MAX relates to the max. number of
>file secriptors the System can have open at a time.

No relation, except if OPEN_MAX is large (256 or so) and that many
files are opened by several processes, then you'll quickly run out of
system fd's.  E.g., on a 16MB system, then defaults give kern.maxfiles =
360, and kern.maxfilesperproc = 360.  If OPEN_MAX or the soft rlimit
is set to 360, then one user process can eat all the system fd's, so
root won't be able to log in.  This requires no special privileges.
This is broken as designed.  It's easy to reduce the hard rlimit or
kern.maxfilesperproc so that a single process can't exhaust all fd's,
but the reasonable defaults of (CHILD_MAX = 40) and (OPEN_MAX = 64) 
require an unreasonable number of system fd's (2560) to satisfy the
worst case.

CHILD_MAX is broken in much the same way as OPEN_MAX.  In fact, almost
everything in <sys/syslimits.h> is broken, e.g.,

ARG_MAX: should be indeterminate so that it can be changed in the kernel
         without having to recompile applications.
LINK_MAX: is indeterminate; depends on the file system.
MAX_CANON, MAX_INPUT: should be indeterminate so that they can be changed
         in drives without having to recompile applications.  Currently
	 unrelated to the limit(s) actually used in drivers.
NAME_MAX: is indeterminate; depends on the file system.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199609271024.UAA19546>