summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBodigrim <andrew.lelechenko@gmail.com>2022-08-10 20:29:25 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2022-08-10 22:41:50 -0400
commit5c24b1b3a9d6a4c2f471fd7d8ec65141a8b46357 (patch)
treea9aca8e33c9df8b7ef701b033b245e5be7c758a0
parent45eb4cbe372eadb8331c6dbc84f14c681b1a8a9b (diff)
downloadhaskell-5c24b1b3a9d6a4c2f471fd7d8ec65141a8b46357.tar.gz
Document that threadDelay / timeout are susceptible to overflows on 32-bit machines
-rw-r--r--libraries/base/GHC/Conc/IO.hs6
-rw-r--r--libraries/base/GHC/Conc/POSIX.hs6
-rw-r--r--libraries/base/GHC/Conc/Windows.hs6
-rw-r--r--libraries/base/GHC/Event/Thread.hs7
-rw-r--r--libraries/base/GHC/Event/TimerManager.hs8
-rw-r--r--libraries/base/GHC/Event/Windows.hsc8
-rw-r--r--libraries/base/GHC/Event/Windows/Thread.hs4
-rw-r--r--libraries/base/System/Timeout.hs4
8 files changed, 48 insertions, 1 deletions
diff --git a/libraries/base/GHC/Conc/IO.hs b/libraries/base/GHC/Conc/IO.hs
index 5674284a3c..344a688d28 100644
--- a/libraries/base/GHC/Conc/IO.hs
+++ b/libraries/base/GHC/Conc/IO.hs
@@ -189,6 +189,9 @@ closeFdWith close fd
-- when the delay has expired, but the thread will never continue to
-- run /earlier/ than specified.
--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+-- Consider using @Control.Concurrent.Thread.Delay.delay@ from @unbounded-delays@ package.
threadDelay :: Int -> IO ()
threadDelay time
#if defined(mingw32_HOST_OS)
@@ -206,6 +209,9 @@ threadDelay time
-- after a given number of microseconds. The caveats associated with
-- 'threadDelay' also apply.
--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
registerDelay :: Int -> IO (TVar Bool)
registerDelay usecs
#if defined(mingw32_HOST_OS)
diff --git a/libraries/base/GHC/Conc/POSIX.hs b/libraries/base/GHC/Conc/POSIX.hs
index 44d142c981..dd9adac461 100644
--- a/libraries/base/GHC/Conc/POSIX.hs
+++ b/libraries/base/GHC/Conc/POSIX.hs
@@ -107,6 +107,9 @@ asyncWriteBA fd isSock len off bufB =
-- when the delay has expired, but the thread will never continue to
-- run /earlier/ than specified.
--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
threadDelay :: Int -> IO ()
threadDelay time
| threaded = waitForDelayEvent time
@@ -118,6 +121,9 @@ threadDelay time
-- | Set the value of returned TVar to True after a given number of
-- microseconds. The caveats associated with threadDelay also apply.
--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
registerDelay :: Int -> IO (TVar Bool)
registerDelay usecs
| threaded = waitForDelayEventSTM usecs
diff --git a/libraries/base/GHC/Conc/Windows.hs b/libraries/base/GHC/Conc/Windows.hs
index fe452cbe32..50b91aaa45 100644
--- a/libraries/base/GHC/Conc/Windows.hs
+++ b/libraries/base/GHC/Conc/Windows.hs
@@ -95,12 +95,18 @@ asyncWriteBA fd isSock len off bufB =
-- when the delay has expired, but the thread will never continue to
-- run /earlier/ than specified.
--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
threadDelay :: Int -> IO ()
threadDelay = POSIX.threadDelay <!> WINIO.threadDelay
-- | Set the value of returned TVar to True after a given number of
-- microseconds. The caveats associated with threadDelay also apply.
--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
registerDelay :: Int -> IO (TVar Bool)
registerDelay = POSIX.registerDelay <!> WINIO.registerDelay
diff --git a/libraries/base/GHC/Event/Thread.hs b/libraries/base/GHC/Event/Thread.hs
index cf9a769766..4f67a97513 100644
--- a/libraries/base/GHC/Event/Thread.hs
+++ b/libraries/base/GHC/Event/Thread.hs
@@ -55,6 +55,10 @@ import System.Posix.Types (Fd)
-- There is no guarantee that the thread will be rescheduled promptly
-- when the delay has expired, but the thread will never continue to
-- run /earlier/ than specified.
+--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
threadDelay :: Int -> IO ()
threadDelay usecs = mask_ $ do
mgr <- getSystemTimerManager
@@ -65,6 +69,9 @@ threadDelay usecs = mask_ $ do
-- | Set the value of returned TVar to True after a given number of
-- microseconds. The caveats associated with threadDelay also apply.
--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
registerDelay :: Int -> IO (TVar Bool)
registerDelay usecs = do
t <- atomically $ newTVar False
diff --git a/libraries/base/GHC/Event/TimerManager.hs b/libraries/base/GHC/Event/TimerManager.hs
index 533558a8cc..508b9e0a0a 100644
--- a/libraries/base/GHC/Event/TimerManager.hs
+++ b/libraries/base/GHC/Event/TimerManager.hs
@@ -212,6 +212,10 @@ expirationTime us = do
-- returned 'TimeoutKey' can be used to later unregister or update the
-- timeout. The timeout is automatically unregistered after the given
-- time has passed.
+--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
registerTimeout :: TimerManager -> Int -> TimeoutCallback -> IO TimeoutKey
registerTimeout mgr us cb = do
!key <- newUnique (emUniqueSource mgr)
@@ -231,6 +235,10 @@ unregisterTimeout mgr (TK key) =
-- | Update an active timeout to fire in the given number of
-- microseconds.
+--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
updateTimeout :: TimerManager -> TimeoutKey -> Int -> IO ()
updateTimeout mgr (TK key) us = do
expTime <- expirationTime us
diff --git a/libraries/base/GHC/Event/Windows.hsc b/libraries/base/GHC/Event/Windows.hsc
index 778d6e08e5..007259c846 100644
--- a/libraries/base/GHC/Event/Windows.hsc
+++ b/libraries/base/GHC/Event/Windows.hsc
@@ -853,6 +853,10 @@ expirationTime mgr us = do
-- The timeout is automatically unregistered when it fires.
--
-- The 'TimeoutCallback' will not be called more than once.
+--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
{-# NOINLINE registerTimeout #-}
registerTimeout :: Manager -> Int -> TimeoutCallback -> IO TimeoutKey
registerTimeout mgr@Manager{..} uSrelTime cb = do
@@ -866,6 +870,10 @@ registerTimeout mgr@Manager{..} uSrelTime cb = do
-- | Update an active timeout to fire in the given number of seconds (from the
-- time 'updateTimeout' is called), instead of when it was going to fire.
-- This has no effect if the timeout has already fired.
+--
+-- Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+--
updateTimeout :: Manager -> TimeoutKey -> Seconds -> IO ()
updateTimeout mgr (TK key) relTime = do
now <- getTime (mgrClock mgr)
diff --git a/libraries/base/GHC/Event/Windows/Thread.hs b/libraries/base/GHC/Event/Windows/Thread.hs
index 57faa9de80..14f3dda42f 100644
--- a/libraries/base/GHC/Event/Windows/Thread.hs
+++ b/libraries/base/GHC/Event/Windows/Thread.hs
@@ -19,6 +19,8 @@ ensureIOManagerIsRunning = wakeupIOManager
interruptIOManager :: IO ()
interruptIOManager = interruptSystemManager
+-- | Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
threadDelay :: Int -> IO ()
threadDelay usecs = mask_ $ do
m <- newEmptyIOPort
@@ -26,6 +28,8 @@ threadDelay usecs = mask_ $ do
reg <- registerTimeout mgr usecs $ writeIOPort m () >> return ()
readIOPort m `onException` unregisterTimeout mgr reg
+-- | Be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
registerDelay :: Int -> IO (TVar Bool)
registerDelay usecs = do
t <- newTVarIO False
diff --git a/libraries/base/System/Timeout.hs b/libraries/base/System/Timeout.hs
index f3081e7082..3cca893c4d 100644
--- a/libraries/base/System/Timeout.hs
+++ b/libraries/base/System/Timeout.hs
@@ -58,7 +58,9 @@ instance Exception Timeout where
-- is available within @n@ microseconds (@1\/10^6@ seconds). In case a result
-- is available before the timeout expires, @Just a@ is returned. A negative
-- timeout interval means \"wait indefinitely\". When specifying long timeouts,
--- be careful not to exceed @maxBound :: Int@.
+-- be careful not to exceed @maxBound :: Int@, which on 32-bit machines is only
+-- 2147483647 μs, less than 36 minutes.
+-- Consider using @Control.Concurrent.Timeout.timeout@ from @unbounded-delays@ package.
--
-- >>> timeout 1000000 (threadDelay 1000 *> pure "finished on time")
-- Just "finished on time"