svn commit: r249859 - head/lib/libc/sys

Jilles Tjoelker jilles at stack.nl
Fri Apr 26 15:59:34 UTC 2013


On Thu, Apr 25, 2013 at 09:56:01PM +1000, Bruce Evans wrote:
> On Wed, 24 Apr 2013, Jilles Tjoelker wrote:

> > Log:
> >  getdtablesize(2): Describe what this function actually does.

> >  getdtablesize() returns the limit on new file descriptors; this
> >  says nothing about existing descriptors.

> It's still quite broken.

> > Modified: head/lib/libc/sys/getdtablesize.2
> > ==============================================================================
> > --- head/lib/libc/sys/getdtablesize.2	Wed Apr 24 21:21:03 2013	(r249858)
> > +++ head/lib/libc/sys/getdtablesize.2	Wed Apr 24 21:24:35 2013	(r249859)
> > @@ -28,12 +28,12 @@
> > .\"     @(#)getdtablesize.2	8.1 (Berkeley) 6/4/93
> > .\" $FreeBSD$
> > .\"
> > -.Dd June 4, 1993
> > +.Dd April 24, 2013
> > .Dt GETDTABLESIZE 2
> > .Os
> > .Sh NAME
> > .Nm getdtablesize
> > -.Nd get descriptor table size
> > +.Nd get file descriptor limit

> Now its name doesn't match its description, and the reason for this is
> not documented.

This seems to be the case on most systems that have this function.

> This function is almost obsolete.  In POSIX, it is spelled {OPEN_MAX}
> or sysconf(__SC_OPEN_MAX).  It is sometimes misspelled OPEN_MAX.

There is a difference between sysconf(_SC_OPEN_MAX) and getdtablesize():
the latter also takes maxfilesperproc and rctl(8) rules into account.

> I prepared to remove the broken definition of OPEN_MAX, but never committed
> the final step.  /usr/src has very few misuses of OPEN_MAX now, so removing
> the definition wouldn't be too hard.  Most uses are in compatibility
> cruft.  E.g., the following from
> crypto/openssh/openbsd-compat/bsd-closefrom.c
> which is confused about related things:

> [snip]
If that code is compiled at all, it is a bug. We have closefrom() and
OpenSSH should use it.

> ... in 4.4BSD and FreeBSD, both sysconf(_SC_OPEN_MAX) are just wrappers for
> the resource limit (sysconf() is a libc wrapper and getdtablesize() is
> a syscall wrapper).  Actually, in FreeBSD, getdtablesize() is not even the
> rlmint -- it is the min() of the rlimit and the global sysctl integer
> maxfilesperproc.  Here the bug is in the rlimit.  For the rlimit,
> maxfilesperproc is only used when the rlimit is set and when it is used
> in the kernel.  But when the rlimit is returned to userland, via
> getrlimit(), maxfilesperproc is not used, so the rlimit may be wrong if
> maxfileperproc was lowered after setting the rlimit.

I don't like the idea of rlimits changing of "their own will". Changing
maxfileperproc at run time is going to be a bit nasty in any case but
seems not as bad as changing rlimits of running processes.

> [snip]

> > .Sh LIBRARY
> > .Lb libc
> > .Sh SYNOPSIS
> > @@ -41,18 +41,20 @@
> > .Ft int
> > .Fn getdtablesize void
> > .Sh DESCRIPTION
> > -Each process has a fixed size descriptor table,

> Actually, each process has a variable size descriptor table, and
> getdtablesize() doesn't give the size of this table.

> > -which is guaranteed to have at least 20 slots.

> Actually, {OPEN_MAX} is guaranteed by POSIX to be at least
> {_POSIX_OPEN_MAX}, and {_POSIX_OPEN_MAX} is precisely 20.  But these
> guarantees and similar ones for stdio's FOPEN_MAX have always been
> broken in FreeBSD, since anyone can reduce the rlimit below 20.
> Privileged users can break the gurantee even more easily by setting
> maxfilesperproc below 20.  When POSIX standardized rlimits, it didn't
> properly specify the behaviour for the interaction of the rlimit with
> {OPEN_MAX}, at least initially.  The 2001 version breaks its own
> guarantee by just saying that if the rlimit is reduced to less than
> {_POSIX_OPEN_MAX}, then "unexpected behaviour may occur".  Reductions
> from 707112 to less than 20 won't occur often in practice.  Ones from
> 707112 to less than the largest currently open fd (+1) are more common
> in practice and cause similarly unexpected behaviours, but the 2001
> version of POSIX is even more underspecified for them.

Recent versions of POSIX allow {OPEN_MAX} to be based on the rlimit. In
that case, it may change when the rlimit is changed.

I think the "unexpected behaviour may occur" is intended to allow both
permitting an rlimit below 20 and forbidding such a change. In the
former case, the execution environment is no longer POSIX compliant. In
particular, on most systems, setting the rlimit to 0 disables all
operations that need to open a new file descriptor and it is
implementation-specific which operations are affected (in addition to
those returning a file descriptor).

> > -The entries in
> > -the descriptor table are numbered with small integers starting at 0.

> Still correct, though not very interesting.

> > The
> > .Fn getdtablesize
> > -system call returns the size of this table.
> > +system call returns the maximum number of file descriptors
> > +that the current process may open.

> Actually, the process may open more than this number, after raising its
> (soft) rlimit, if this is possible.

True, but this requires different function calls than just ones
allocating file descriptors.

> > +The maximum file descriptor number that the system may assign
> > +is the return value minus one.
> > +Existing file descriptor numbers may be higher
> > +if the limit was lowered after they were opened.
> > .Sh SEE ALSO
> > .Xr close 2 ,
> > +.Xr closefrom 2 ,
> > .Xr dup 2 ,
> > -.Xr open 2 ,
> > -.Xr select 2
> > +.Xr getrlimit 2 ,
> > +.Xr sysconf 2
> > .Sh HISTORY
> > The
> > .Fn getdtablesize

I suppose rctl(8) can be added here.

> open(2) is probably still relevant.  It seems to be the natuaral place to
> document {OPEN_MAX}, but it says nothing about any spelling of OPEN_MAX.
> (The closest that it gets is saying that [EMFILE] means that the process
> has reached its limit for open file descriptors.

Not sure if open(2) is indeed the right place.

>  apropos(1) gives nothing appropriate for OPEN_MAX.  In fact, even
>  OPEN_MAX is not mentioned in any man page.  Only _SC_OPEN_MAX is
>  mentioned (in sysconf(3)), and it is misdescribed as being the
>  maximum number of open files per user id.)

Yes, wrong.

> Some limits are better descrtibed than {OPEN_MAX}, in intro(2).  I was
> a little surprised to not find much about the file descriptor limits
> there.  In fact, there is a very incomplete description of them for
> [EMFILE].  This says that the limit is the release one of 64 (that was
> for the 4.4BSD-Lite* release) and that getdtablesize(2) will obtain the
> current limit.  Similar historical limits have been changed to POSIX
> ones mainly for pathnames.

Hmm, that sentence about a limit of 64 can go away.

-- 
Jilles Tjoelker


More information about the svn-src-all mailing list