[SOLVED] Safe elimination of `unsafePerformIO`?

I am seeking some advice on part of Stack’s code. It has:

entrypointMVar :: MVar Bool
{-# NOINLINE entrypointMVar #-}
entrypointMVar = unsafePerformIO (newMVar False)

and that gets used in one place only, namely:

entrypoint :: (HasProcessContext env, HasLogFunc env)
           => Config
           -> DockerEntrypoint
           -> RIO env ()
entrypoint config@Config{} DockerEntrypoint{..} =
  modifyMVar_ entrypointMVar $ \alreadyRan -> do ...

The STAN tool advises me to do away with the unsafePerformIO.

I am assuming that I could do that with:

newEntrypointMVar :: RIO env (MVar Bool)
{-# NOINLINE newEntrypointMVar #-}
newEntrypointMVar = liftIO $ newMVar False

entrypoint config@Config{} DockerEntrypoint{..} = do
  entryPointMVar <- newEntryPointMVar
  modifyMVar_ entrypointMVar $ \alreadyRan -> do ...

My questions are:

  1. Could there have been some important reason for the original use of unsafePerformIO that I am missing?
  2. What could have been the purpose of the NOINLINE pragma? Is it still needed?

Any help, gratefully received.

2 Likes

This is an idiom for global mutable variables. Top level mutable state - HaskellWiki

So I think stan just doesn’t understand the idiom and this is a false positive.

6 Likes

As @Ambrose pointed out, this is an idiom for global mutable variables. Answering your questions in case it helps understand what is going on:

In this case, unsafePerformIO is used to create a single MVar for the top-level declaration of entrypointMVar. The NOINLINE is critical because it would instead create a new MVar for each call to entrypoint if it were inlined. The RIO env (MVar Bool) version creates a new MVar for each call to entrypoint, so it is not the same as the existing code.

Ignoring the Stan warning should be fine. If you prefer to avoid using unsafePerformIO, you can refactor the code so that the MVar is included in the env and initialize it (using MonadIO) when the env is initialized. The above refactored code is not a safe refactoring.

5 Likes

Many thanks for the advice, explanations and references.

4 Likes