GHC API messes up signal handlers
A side-effect of using the
runGhc function is that some signal handlers are modified and not restored afterwards (see function
initGhcMonad). In particular, the handler for
SIGINT installed by ghc throws an exception to a thread stored in a global variable, which initially corresponds to the thread from which
runGhc was run.
This is a particularly problematic for programs that wish to run ghc "in the background" on its own thread. For example, consider this code:
import qualified GHC import qualified MonadUtils as GHC import qualified GHC.Paths as GHC import Control.Concurrent ( forkIO, threadDelay ) main = do putStrLn "waiting for 5 seconds..." threadDelay $ 5 * 1000 * 1000 putStrLn "starting..." forkIO $ GHC.runGhc (Just GHC.libdir) (GHC.liftIO $ putStrLn "hello") putStrLn "waiting for 10 seconds" threadDelay $ 10 * 1000 * 1000 putStrLn "exiting after final wait"
One can interrupt this program with Ctrl-C during the first five seconds of execution only.
It is not clear to me how one can safely workaround this problem. For instance, one could manually restore the program's original handlers at the beginning of execution, that is, transform:
into something like this:
runGhc $ (liftIO restoreProgramHandlers >> action)
but I don't know if this is safe (i.e., what happens if ghc is run without its own handlers installed).