diff options
author | Simon Marlow <marlowsd@gmail.com> | 2016-12-02 14:32:24 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-12-02 15:31:46 -0500 |
commit | d9e7a69290c39f6075b70c218fbcf7f85682e9cb (patch) | |
tree | b67193fa877707a054b3bfa280a54a1875f40f1e | |
parent | 706d708a4bb74e27437ea2ec37e4999a4615b0e8 (diff) | |
download | haskell-d9e7a69290c39f6075b70c218fbcf7f85682e9cb.tar.gz |
fdReady: use poll() instead of select()
select() is limited to 1024 file descriptors. This actually blew up
in a very hard-to-debug way in our production system when using the
hinotify package.
Test Plan:
libraries/tests pass, paricularly hGetBuf001 which exercises this
code.
Reviewers: niteria, erikd, austin, hvr, bgamari
Reviewed By: bgamari
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D2785
GHC Trac Issues: #12912
(cherry picked from commit f46369b8a1bf90a3bdc30f2b566c3a7e03672518)
-rw-r--r-- | libraries/base/cbits/inputReady.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/libraries/base/cbits/inputReady.c b/libraries/base/cbits/inputReady.c index 8714eea752..230e592260 100644 --- a/libraries/base/cbits/inputReady.c +++ b/libraries/base/cbits/inputReady.c @@ -7,6 +7,9 @@ /* select and supporting types is not Posix */ /* #include "PosixSource.h" */ #include "HsBase.h" +#if !defined(_WIN32) +#include <poll.h> +#endif /* * inputReady(fd) checks to see whether input is available on the file @@ -16,19 +19,41 @@ int fdReady(int fd, int write, int msecs, int isSock) { - if -#if defined(_WIN32) - ( isSock ) { + +#if !defined(_WIN32) + + // We only handle msecs == 0 on non-Windows, because this is the + // only case we need. Non-zero waiting is handled by the IO manager. + if (msecs != 0) { + fprintf(stderr, "fdReady: msecs != 0, this shouldn't happen"); + abort(); + } + + struct pollfd fds[1]; + + fds[0].fd = fd; + fds[0].events = write ? POLLOUT : POLLIN; + fds[0].revents = 0; + + int res; + while ((res = poll(fds, 1, 0)) < 0) { + if (errno != EINTR) { + return (-1); + } + } + + // res is the number of FDs with events + return (res > 0); + #else - ( 1 ) { -#endif + + if (isSock) { int maxfd, ready; fd_set rfd, wfd; struct timeval tv; if ((fd >= (int)FD_SETSIZE) || (fd < 0)) { - /* avoid memory corruption on too large FDs */ - errno = EINVAL; - return -1; + fprintf(stderr, "fdReady: fd is too big"); + abort(); } FD_ZERO(&rfd); FD_ZERO(&wfd); @@ -54,7 +79,6 @@ fdReady(int fd, int write, int msecs, int isSock) /* 1 => Input ready, 0 => not ready, -1 => error */ return (ready); } -#if defined(_WIN32) else { DWORD rc; HANDLE hFile = (HANDLE)_get_osfhandle(fd); |