Messages in this thread | | | Date | Tue, 10 Nov 1998 16:42:02 -0800 | From | David Mosberger <> | Subject | select()/poll() bug report |
| |
This is a Linux kernel v2.1.xxx bug report. Linus says the bug has been around forever and that it is unlikely to get fixed for v2.2 unless someone sends him a patch that is "obviously correct" and reasonably clean and fast.
IMHO, this bug is quite serious because any web server allowing more than 256 HTTP/1.1 connections will see at least serious performance problems or even complete client lock outs (were a client can't connect to the web server even though the machine is mostly idle).
Anyone have any cycles available to look into this? If not, maybe it could at least be documented somewhere as a known bug?
Thanks,
--david ---- The following program demonstrates a bug in Linux v2.1.127. The problem is that if a select or poll attempts to monitor more than 256 filedescriptors, all but the 256 first filedescriptors are silently ignored. This has the potential to lead to performance bugs or outright application failures. The problem is due to the fact one page can hold only 256 "struct poll_table_entry" elements. Thus, __MAX_POLL_TABLE_ENTRIES in include/linux/poll.h gets defined to 256. When calling poll_wait() and the poll table is full, the passed file pointer is sliently dropped.
The expected behavior of the program is that after starting it up, you hit the Enter key and then see the output:
$ a.out
nfds=1 bit 256 is set
However, with Linux v2.1.127, entering an empty line will _not_ cause the select() to return.
<----------------------------------------------------------------> #include <fcntl.h> #include <netinet/in.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/resource.h> /* grrr, must come after sys/types.h for BSD */
#define panic(foo) { perror (foo); exit (-1); }
#define NUM_FDS 257 #define THE_INDEX 256
int main (int argc, char **argv) { int i, fd, nfds, max_fd = -1; struct rlimit rlimit; fd_set rdfds;
/* boost open file limit to the max: */ if (getrlimit (RLIMIT_NOFILE, &rlimit) < 0) panic ("getrlimit"); rlimit.rlim_cur = rlimit.rlim_max; if (setrlimit (RLIMIT_NOFILE, &rlimit) < 0) panic ("setrlimit");
FD_ZERO (&rdfds); for (i = 0; i < NUM_FDS; ++i) { if (i == THE_INDEX) fd = dup (0); else { fd = socket (AF_INET, SOCK_STREAM, 0); if (fd < 0) panic ("socket"); } if (fd < 0) panic ("open"); if (fd > max_fd) max_fd = fd; FD_SET (fd, &rdfds); } nfds = select (max_fd + 1, &rdfds, 0, 0, 0); printf ("nfds=%d\n", nfds); for (i = 0; i < NUM_FDS; ++i) if (FD_ISSET (i+3, &rdfds)) printf ("bit %d is set\n", i); }
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |