Don't spin if accept() fails because it is out of file descriptors,

instead set a flag that skips the listening socket from the poll()
event loop. The flag is cleared whenever a file descriptor is closed
allowing accept() to be retried.
Explained by deraadt@
This commit is contained in:
Alexandre Ratchov 2012-03-29 22:13:49 +02:00
parent 2b23e80702
commit 2d72ee38d1
4 changed files with 12 additions and 4 deletions

View File

@ -73,6 +73,7 @@ struct timespec file_ts;
struct filelist file_list;
struct timo *timo_queue;
unsigned timo_abstime;
int file_slowaccept = 0;
#ifdef DEBUG
long long file_wtime, file_utime;
#endif

View File

@ -68,6 +68,7 @@ struct file {
LIST_HEAD(filelist,file);
extern struct filelist file_list;
extern int file_slowaccept;
#ifdef DEBUG
extern long long file_wtime, file_utime;

View File

@ -175,6 +175,8 @@ listen_pollfd(struct file *file, struct pollfd *pfd, int events)
{
struct listen *f = (struct listen *)file;
if (file_slowaccept)
return 0;
pfd->fd = f->fd;
pfd->events = POLLIN;
return 1;
@ -190,10 +192,13 @@ listen_revents(struct file *file, struct pollfd *pfd)
if (pfd->revents & POLLIN) {
caddrlen = sizeof(caddrlen);
sock = accept(f->fd, &caddr, &caddrlen);
if (sock < 0) {
/* XXX: should we kill the socket here ? */
perror("accept");
while ((sock = accept(f->fd, &caddr, &caddrlen)) < 0) {
if (errno == EINTR)
continue;
if (errno == ENFILE || errno == EMFILE)
file_slowaccept = 1;
else
perror("accept");
return 0;
}
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {

View File

@ -139,6 +139,7 @@ pipe_close(struct file *file)
struct pipe *f = (struct pipe *)file;
close(f->fd);
file_slowaccept = 0;
}
off_t