- 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;
+ 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 {
+ perror("select");
+ barf("select failed");
+ }
+ }
+
+ /* We got a signal; could be one of ours. If so, we need
+ * to start up the signal handler straight away, otherwise
+ * we could block for a long time before the signal is
+ * serviced.
+ */
+#if defined(RTS_USER_SIGNALS)
+ if (signals_pending()) {
+ startSignalHandlers();
+ return; /* still hold the lock */
+ }