From 2d72ee38d148b3f32c53635fdd037ca6b7909331 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Thu, 29 Mar 2012 22:13:49 +0200 Subject: [PATCH] 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@ --- aucat/file.c | 1 + aucat/file.h | 1 + aucat/listen.c | 13 +++++++++---- aucat/pipe.c | 1 + 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/aucat/file.c b/aucat/file.c index 107341e..d1034ed 100644 --- a/aucat/file.c +++ b/aucat/file.c @@ -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 diff --git a/aucat/file.h b/aucat/file.h index 2ac4bc0..6a8312c 100644 --- a/aucat/file.h +++ b/aucat/file.h @@ -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; diff --git a/aucat/listen.c b/aucat/listen.c index bdf7c72..31b7f4b 100644 --- a/aucat/listen.c +++ b/aucat/listen.c @@ -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) { diff --git a/aucat/pipe.c b/aucat/pipe.c index 8390092..528f7f4 100644 --- a/aucat/pipe.c +++ b/aucat/pipe.c @@ -139,6 +139,7 @@ pipe_close(struct file *file) struct pipe *f = (struct pipe *)file; close(f->fd); + file_slowaccept = 0; } off_t