Date: Tue, 17 Oct 95 00:26:42 -0700 From: Bakul Shah <bakul@netcom.com> To: Terry Lambert <terry@lambert.org> Cc: hackers@freefall.freebsd.org, current@freefall.freebsd.org Subject: Re: getdtablesize() broken? Message-ID: <199510170726.AAA00821@netcom17.netcom.com> In-Reply-To: Your message of "Mon, 16 Oct 95 11:31:02 PDT." <199510161831.LAA25019@phaeton.artisoft.com>
next in thread | previous in thread | raw e-mail | index | archive | help
> Using FD_SETSIZE or using RLIMIT_NOFILE, or getting the current open
> descriptor limit from the kernel (when the application has an explicit
> bitvector element limitation set at compile time, not because of a
> check for FD_SETSIZE by because declaration of a bit vector uses the
> FD_SETSIZE to declare the vector length) is equally stupid and equally
> succeptible to screwups.
> The "correct" way is to get rid of the interfaces which are succeptible
> to bad programming style. The user *SHOULD* be using the highest open
> FD in the set of FD's being selected upon, *NOT* some arbitrary constant.
My mistake. I didn't explicitly state that I was bitching about
an *in-kernel* limitation. Granted that an application should use
what you suggest but the problem is that a {Free|Net}BSD _kernel_
restricts nfds that can be passed to select() to FD_SETSIZE. I
can open, say, 1000 sockets, there is no way I can select on an fd
>= FD_SETSIZE.
Unshar the attached little program and try this test.
% cc x.c
% limit openefiles 500 # you may need to do `limit descriptors 500'
% a.out 500 </dev/null
If you can select on fd 499, the program will terminate silently.
Instead, you will see
select error Invalid argument when fd = 256
(BTW, If you don't change the limit, you will discover an off by
one bug: the default limit is 64 but you can only open 63 fds)
So I can do everything with fd > 255 except select(). This
happens because of this line in /sys/kern/sys_generic.c:select()
if (uap->nd > FD_SETSIZE)
It should be replaced with
if (uap->nd > p->fd->fd_nfiles)
It is this hardwired use of FD_SETSIZE *in* the kernel I am
bitching about.
There *are* scalability problems with select() and we can
use a more scalable interface but regardless, select() needs
to work with any valid file descriptor.
--bakul
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 10/17/1995 07:18 UTC by bakul@netcom17
# Source directory /u7/bakul
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 502 -rw-r--r-- x.c
#
# ============= x.c ==============
if test -f 'x.c' -a X"$1" != X"-c"; then
echo 'x - skipping x.c (File already exists)'
else
echo 'x - extracting x.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'x.c' &&
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
X
int main(int argc, char**argv) {
X int n = argc > 1 ? atoi(argv[1]) : 257;
X int * bits = calloc((n+31)/32, sizeof(int));
X int i;
X
X for (i = 3; i < n; i++) {
X int fd = dup(0);
X if (fd < 0) {
X fprintf(stderr, "Can only get %d descriptors\n", i);
X exit(1);
X }
X bits[fd/32] |= 1<<(fd%32);
X if (select(fd+1, bits, 0, 0, 0) < 0) {
X fprintf(stderr, "select error %s when fd = %d\n",
X strerror(errno), fd);
X exit(1);
X }
X }
X exit(0);
}
SHAR_EOF
chmod 0644 x.c ||
echo 'restore of x.c failed'
Wc_c="`wc -c < 'x.c'`"
test 502 -eq "$Wc_c" ||
echo 'x.c: original size 502, current size' "$Wc_c"
fi
exit 0
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199510170726.AAA00821>
