Date: Sun, 13 Jun 1999 00:44:50 -0400 (EDT) From: Brian Feldman <green@unixhelp.org> To: hackers@FreeBSD.org Subject: select(2) breakage Message-ID: <Pine.BSF.4.10.9906130033380.17648-100000@janus.syracuse.net>
index | next in thread | raw e-mail
I'm using the attached program which I wrote today (don't ask why, I think
I just wanted to beat the heck out of FreeBSD!) I have maxusers 200, a
MAXFILES=65536, and the limits set to allow me to use the program
fully (all 30000 ports; I don't want to monopolize EVERY port...) When
run, select doesn't time out after 60 seconds like it should.
Another problem that came up with this: I originally started at port 1024.
I monopolized 30000 ports (almost all consecutive, of course). When I try to
connect() a TCP socket as non-root, it fails with EAGAIN (I only tracked it
far enough down as in_pcbbind().) It seems that eventually it gives up trying
to find a port... :-/
Brian Feldman _ __ ___ ____ ___ ___ ___
green@unixhelp.org _ __ ___ | _ ) __| \
FreeBSD: The Power to Serve! _ __ | _ \._ \ |) |
http://www.freebsd.org _ |___/___/___/
"<green_> THAT'S WRONG WRONG WRONG!"
/*-
* Copyright (c) 1999 Brian Fundakowski Feldman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
int
anothersocket(u_short port) {
struct sockaddr_in sin;
int fd, serrno;
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
return fd;
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
serrno = errno;
close(fd);
errno = serrno;
return -1;
}
listen(fd, 1);
return fd;
}
int
allocatesockets(int *fdvec, u_short *portvec, int nsockets) {
int fd, ncreated = 0, serrno;
u_short port = 32768;
while (nsockets) {
if (++port == 65535)
break;
if ((fd = anothersocket(port)) == -1)
if (errno == ENFILE || errno == EMFILE) {
serrno = errno;
close(fdvec[--ncreated]);
errno = serrno;
break;
} else
continue;
portvec[ncreated] = port;
fdvec[ncreated++] = fd;
nsockets--;
}
return ncreated;
}
int
main(int argc, char **argv) {
int fdvec[30000];
u_short portvec[30000];
int nsockets, tmp, highestsock;
fd_set odescriptors, ndescriptors;
struct timeval timeout;
nsockets = allocatesockets(fdvec, portvec,
sizeof(fdvec) / sizeof(fdvec[0]));
printf("%s started: %d PF_INET SOCK_STREAM sockets ready\n",
strrchr(argv[0], '/') + 1, nsockets);
highestsock = fdvec[nsockets - 1] + 1;
FD_ZERO(&odescriptors);
for (tmp = 0; tmp < nsockets; tmp++)
FD_SET(fdvec[tmp], &odescriptors);
for (;;) {
int nfound, curnum, nset;
int *selected;
u_short *selectedports;
const struct timespec sleeper = { 0, 100000000 };
timeout.tv_sec = 60;
timeout.tv_usec = 0;
ndescriptors = odescriptors;
if ((nfound = select(highestsock, &ndescriptors, NULL, NULL,
&timeout)) < 1) {
if (nfound == -1)
perror("select()");
else
printf("no select() action");
continue;
}
selected = malloc(nfound * sizeof(int));
selectedports = malloc(nfound * sizeof(u_short));
for (curnum = nset = 0; nset < nfound; curnum++) {
if (!FD_ISSET(fdvec[curnum], &ndescriptors))
continue;
selectedports[nset] = portvec[curnum];
selected[nset++] = accept(fdvec[curnum], NULL, NULL);
}
printf("Sockets ready:\n\t");
for (nset = 0; nset < nfound; nset++)
printf("%d,", selectedports[nset]);
putchar('\n');
for (nset = 0; nset < nfound; nset++)
close(selected[nset]);
free(selected);
free(selectedports);
nanosleep(&sleeper, NULL);
}
}
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.10.9906130033380.17648-100000>
