Skip site navigation (1)Skip section navigation (2)
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>

next in thread | raw e-mail | index | archive | help
  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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.10.9906130033380.17648-100000>