diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-12-20 10:26:24 -0500 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-12-22 23:40:32 -0500 |
commit | 35267f077ac226d4fbe3f14fce2dd240fb61e188 (patch) | |
tree | bd59fff53fc59581bf18823cbff79d23997b8267 | |
parent | 02ed7d783244bd95ee897825650426de6f5fb3e2 (diff) | |
download | haskell-35267f077ac226d4fbe3f14fce2dd240fb61e188.tar.gz |
base: Fix event manager shutdown race on non-Linux platforms
During shutdown it's possible that we will attempt to use a closed fd
to wakeup another capability's event manager. On the Linux eventfd path
we were careful to handle this. However on the non-Linux path we failed
to do so. Fix this.
-rw-r--r-- | libraries/base/GHC/Event/Control.hs | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/libraries/base/GHC/Event/Control.hs b/libraries/base/GHC/Event/Control.hs index d80e054182..83b64fbb47 100644 --- a/libraries/base/GHC/Event/Control.hs +++ b/libraries/base/GHC/Event/Control.hs @@ -50,7 +50,7 @@ import System.Posix.Types (Fd) import Foreign.C.Error (throwErrnoIfMinus1, eBADF) import Foreign.C.Types (CULLong(..)) #else -import Foreign.C.Error (eAGAIN, eWOULDBLOCK) +import Foreign.C.Error (eAGAIN, eWOULDBLOCK, eBADF) #endif data ControlMessage = CMsgWakeup @@ -211,8 +211,15 @@ sendWakeup c = do _ | n /= -1 -> return () | otherwise -> do errno <- getErrno - when (errno /= eAGAIN && errno /= eWOULDBLOCK) $ - throwErrno "sendWakeup" + isDead <- readIORef (controlIsDead c) + case () of + _ -- Someone else has beat us to waking it up + | errno == eAGAIN -> return () + | errno == eWOULDBLOCK -> return () + -- we are shutting down + | errno == eBADF && isDead -> return () + -- something bad happened + | otherwise -> throwErrno "sendWakeup" #endif sendDie :: Control -> IO () |