summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2016-12-02 14:32:24 -0500
committerBen Gamari <ben@smart-cactus.org>2016-12-02 15:31:46 -0500
commitd9e7a69290c39f6075b70c218fbcf7f85682e9cb (patch)
treeb67193fa877707a054b3bfa280a54a1875f40f1e
parent706d708a4bb74e27437ea2ec37e4999a4615b0e8 (diff)
downloadhaskell-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.c42
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);