summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libraries/base/GHC/Event/Control.hs7
-rw-r--r--rts/posix/Signals.c17
2 files changed, 22 insertions, 2 deletions
diff --git a/libraries/base/GHC/Event/Control.hs b/libraries/base/GHC/Event/Control.hs
index 747a416343..5dcc66e6dc 100644
--- a/libraries/base/GHC/Event/Control.hs
+++ b/libraries/base/GHC/Event/Control.hs
@@ -68,6 +68,7 @@ data Control = W {
, wakeupReadFd :: {-# UNPACK #-} !Fd
, wakeupWriteFd :: {-# UNPACK #-} !Fd
#endif
+ , didRegisterWakeupFd :: !Bool
} deriving (Show)
#if defined(HAVE_EVENTFD)
@@ -108,13 +109,19 @@ newControl shouldRegister = allocaArray 2 $ \fds -> do
, wakeupReadFd = fromIntegral wake_rd
, wakeupWriteFd = fromIntegral wake_wr
#endif
+ , didRegisterWakeupFd = shouldRegister
}
-- | Close the control structure used by the IO manager thread.
+-- N.B. If this Control is the Control whose wakeup file was registered with
+-- the RTS, then *BEFORE* the wakeup file is closed, we must call
+-- c_setIOManagerWakeupFd (-1), so that the RTS does not try to use the wakeup
+-- file after it has been closed.
closeControl :: Control -> IO ()
closeControl w = do
_ <- c_close . fromIntegral . controlReadFd $ w
_ <- c_close . fromIntegral . controlWriteFd $ w
+ when (didRegisterWakeupFd w) $ c_setIOManagerWakeupFd (-1)
#if defined(HAVE_EVENTFD)
_ <- c_close . fromIntegral . controlEventFd $ w
#else
diff --git a/rts/posix/Signals.c b/rts/posix/Signals.c
index 5fbb917cf8..a2fa07f091 100644
--- a/rts/posix/Signals.c
+++ b/rts/posix/Signals.c
@@ -126,7 +126,7 @@ more_handlers(int sig)
}
// Here's the pipe into which we will send our signals
-static int io_manager_wakeup_fd = -1;
+static volatile int io_manager_wakeup_fd = -1;
static int timer_manager_control_wr_fd = -1;
#define IO_MANAGER_WAKEUP 0xff
@@ -161,7 +161,20 @@ ioManagerWakeup (void)
StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
r = write(io_manager_wakeup_fd, &byte, 1);
#endif
- if (r == -1) { sysErrorBelch("ioManagerWakeup: write"); }
+ /* N.B. If the TimerManager is shutting down as we run this
+ * then there is a possiblity that our first read of
+ * io_manager_wakeup_fd is non-negative, but before we get to the
+ * write the file is closed. If this occurs, io_manager_wakeup_fd
+ * will be written into with -1 (GHC.Event.Control does this prior
+ * to closing), so checking this allows us to distinguish this case.
+ * To ensure we observe the correct ordering, we declare the
+ * io_manager_wakeup_fd as volatile.
+ * Since this is not an error condition, we do not print the error
+ * message in this case.
+ */
+ if (r == -1 && io_manager_wakeup_fd >= 0) {
+ sysErrorBelch("ioManagerWakeup: write");
+ }
}
}