- if (numFound != 0) {
- /*
- File descriptors ready, but we don't know how much time was spent
- in the select(). To interpolate, we compare the time before
- and after the select().
- */
-
-#ifdef linux_TARGET_OS
- /* on Linux, tv is set to indicate the amount of time not
- * slept, so we don't need to gettimeofday() to find out.
- */
- delta += min - (tv.tv_sec * 1000000 + tv.tv_usec);
-#else
- gettimeofday(&tv_after, (struct timezone *) NULL);
- delta += (tv_after.tv_sec - tv_before.tv_sec) * 1000000 +
- tv_after.tv_usec - tv_before.tv_usec;
+ /* Check for any interesting events */
+
+ tv.tv_sec = min / 1000000;
+ tv.tv_usec = min % 1000000;
+
+ while ((numFound = select(maxfd+1, &rfd, &wfd, NULL, &tv)) < 0) {
+ if (errno != EINTR) {
+ /* Handle bad file descriptors by unblocking all the
+ waiting threads. Why? Because a thread might have been
+ a bit naughty and closed a file descriptor while another
+ was blocked waiting. This is less-than-good programming
+ practice, but having the RTS as a result fall over isn't
+ acceptable, so we simply unblock all the waiting threads
+ should we see a bad file descriptor & give the threads
+ a chance to clean up their act.
+
+ Note: assume here that threads becoming unblocked
+ will try to read/write the file descriptor before trying
+ to issue a threadWaitRead/threadWaitWrite again (==> an
+ IOError will result for the thread that's got the bad
+ file descriptor.) Hence, there's no danger of a bad
+ file descriptor being repeatedly select()'ed on, so
+ the RTS won't loop.
+ */
+ if ( errno == EBADF ) {
+ unblock_all = rtsTrue;
+ break;
+ } else {
+ fprintf(stderr,"%d\n", errno);
+ fflush(stderr);
+ perror("select");
+ barf("select failed");
+ }
+ }
+ ACQUIRE_LOCK(&sched_mutex);
+#ifdef RTS_SUPPORTS_THREADS
+ isWorkerBlockedInAwaitEvent = rtsFalse;