diff --git a/libraries/ghc-internal/src/GHC/Internal/System/Environment.hs b/libraries/ghc-internal/src/GHC/Internal/System/Environment.hs index c8f5baefc08cd45b755e5577553c2d181d225a42..fa89b0d3327e4782c4ebe6def485b22b3b266614 100644 --- a/libraries/ghc-internal/src/GHC/Internal/System/Environment.hs +++ b/libraries/ghc-internal/src/GHC/Internal/System/Environment.hs @@ -225,6 +225,13 @@ ioe_missingEnvVar name = ioException (IOError Nothing NoSuchThing "getEnv" -- Throws `Control.Exception.IOException` if @name@ is the empty string or -- contains an equals sign. -- +-- Beware that this function must not be executed concurrently +-- with 'getEnv', 'lookupEnv', 'getEnvironment' and such. One thread +-- reading environment variables at the same time with another one modifying them +-- can result in a segfault, see +-- [Setenv is not Thread Safe](https://www.evanjones.ca/setenv-is-not-thread-safe.html) +-- for discussion. +-- -- @since base-4.7.0.0 setEnv :: String -> String -> IO () setEnv key_ value_ @@ -269,6 +276,13 @@ foreign import ccall unsafe "putenv" c_putenv :: CString -> IO CInt -- Throws `Control.Exception.IOException` if @name@ is the empty string or -- contains an equals sign. -- +-- Beware that this function must not be executed concurrently +-- with 'getEnv', 'lookupEnv', 'getEnvironment' and such. One thread +-- reading environment variables at the same time with another one modifying them +-- can result in a segfault, see +-- [Setenv is not Thread Safe](https://www.evanjones.ca/setenv-is-not-thread-safe.html) +-- for discussion. +-- -- @since base-4.7.0.0 unsetEnv :: String -> IO () #if defined(mingw32_HOST_OS) diff --git a/libraries/ghc-internal/src/GHC/Internal/System/Environment/Blank.hsc b/libraries/ghc-internal/src/GHC/Internal/System/Environment/Blank.hsc index e577456ed577d99ccfa3848d9ffe38c5b4b2dcb8..4c5360220ae86d491d6fc5f42399fb552eb3bc38 100644 --- a/libraries/ghc-internal/src/GHC/Internal/System/Environment/Blank.hsc +++ b/libraries/ghc-internal/src/GHC/Internal/System/Environment/Blank.hsc @@ -109,6 +109,13 @@ getEnvDefault name fallback = fromMaybe fallback <$> getEnv name -- | Like 'GHC.Internal.System.Environment.setEnv', but allows blank environment values -- and mimics the function signature of 'System.Posix.Env.setEnv' from the -- @unix@ package. +-- +-- Beware that this function must not be executed concurrently +-- with 'getEnv', 'lookupEnv', 'getEnvironment' and such. One thread +-- reading environment variables at the same time with another one modifying them +-- can result in a segfault, see +-- [Setenv is not Thread Safe](https://www.evanjones.ca/setenv-is-not-thread-safe.html) +-- for discussion. setEnv :: String {- ^ variable name -} -> String {- ^ variable value -} -> @@ -151,6 +158,13 @@ foreign import ccall unsafe "setenv" -- | Like 'GHC.Internal.System.Environment.unsetEnv', but allows for the removal of -- blank environment variables. May throw an exception if the underlying -- platform doesn't support unsetting of environment variables. +-- +-- Beware that this function must not be executed concurrently +-- with 'getEnv', 'lookupEnv', 'getEnvironment' and such. One thread +-- reading environment variables at the same time with another one modifying them +-- can result in a segfault, see +-- [Setenv is not Thread Safe](https://www.evanjones.ca/setenv-is-not-thread-safe.html) +-- for discussion. unsetEnv :: String -> IO () #if defined(mingw32_HOST_OS) unsetEnv key = withCWString key $ \k -> do