When accept returns EMFILE or ENFILE, it also drops a pending connection. You may argue that is corner case, but still it can be avoided by code adjustment. The example program is attached. --- linux-2.6.9/net/socket.c Mon Oct 18 14:53:50 2004 +++ linux/net/socket.c Mon Nov 15 16:09:37 2004 @@ -362,7 +362,7 @@ * but we take care of internal coherence yet. */ -int sock_map_fd(struct socket *sock) +int sock_create_fd(struct socket *sock, struct file **filep) { int fd; struct qstr this; @@ -372,6 +372,7 @@ * Find a file descriptor suitable for return to the user. */ + *filep = NULL; fd = get_unused_fd(); if (fd >= 0) { struct file *file = get_empty_filp(); @@ -404,13 +405,36 @@ file->f_mode = FMODE_READ | FMODE_WRITE; file->f_flags = O_RDWR; file->f_pos = 0; - fd_install(fd, file); + *filep = file; } out: return fd; } +static inline void sock_install_fd(struct sock *sock, int fd, struct file *file) +{ + fd_install(fd, file); +} + +static inline void sock_release_fd(struct sock *sock, int fd, struct file *file) +{ + fput(file); + put_unused_fd(fd); +} + +int sock_map_fd(struct sock *sock) +{ + int fd; + struct file *file; + + fd = sock_create_fd(sock, &file); + if (fd >= 0) + sock_install_fd(sock, fd, file); + + return fd; +} + /** * sockfd_lookup - Go from a file number to its socket slot * @fd: file handle @@ -1349,6 +1373,8 @@ struct socket *sock, *newsock; int err, len; char address[MAX_SOCK_ADDR]; + int newfd; + struct file *newfile; sock = sockfd_lookup(fd, &err); if (!sock) @@ -1371,24 +1397,29 @@ */ __module_get(newsock->ops->owner); + newfd = sock_create_fd(newsock, &newfile); + if (newfd < 0) { + err = newfd; + goto out_release; + } + err = sock->ops->accept(sock, newsock, sock->file->f_flags); if (err < 0) - goto out_release; + goto out_fd; if (upeer_sockaddr) { if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { err = -ECONNABORTED; - goto out_release; + goto out_fd; } err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); if (err < 0) - goto out_release; + goto out_fd; } /* File flags are not inherited via accept() unlike another OSes. */ - if ((err = sock_map_fd(newsock)) < 0) - goto out_release; + sock_install_fd(newsock, newfd, newfile); security_socket_post_accept(sock, newsock); @@ -1396,6 +1427,8 @@ sockfd_put(sock); out: return err; +out_fd: + sock_release_fd(newsock, newfd, newfile); out_release: sock_release(newsock); goto out_put;