diff options
author | Bodigrim <andrew.lelechenko@gmail.com> | 2022-08-10 20:29:25 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-08-10 22:41:50 -0400 |
commit | 5c24b1b3a9d6a4c2f471fd7d8ec65141a8b46357 (patch) | |
tree | a9aca8e33c9df8b7ef701b033b245e5be7c758a0 /libraries | |
parent | 45eb4cbe372eadb8331c6dbc84f14c681b1a8a9b (diff) | |
download | haskell-5c24b1b3a9d6a4c2f471fd7d8ec65141a8b46357.tar.gz |
Document that threadDelay / timeout are susceptible to overflows on 32-bit machines
Diffstat (limited to 'libraries')
-rw-r--r-- | libraries/base/GHC/Conc/IO.hs | 6 | ||||
-rw-r--r-- | libraries/base/GHC/Conc/POSIX.hs | 6 | ||||
-rw-r--r-- | libraries/base/GHC/Conc/Windows.hs | 6 | ||||
-rw-r--r-- | libraries/base/GHC/Event/Thread.hs | 7 | ||||
-rw-r--r-- | libraries/base/GHC/Event/TimerManager.hs | 8 | ||||
-rw-r--r-- | libraries/base/GHC/Event/Windows.hsc | 8 | ||||
-rw-r--r-- | libraries/base/GHC/Event/Windows/Thread.hs | 4 | ||||
-rw-r--r-- | libraries/base/System/Timeout.hs | 4 |
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" |