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:
runGhc action
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).
Trac metadata
Trac field | Value |
---|---|
Version | 6.12.3 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | GHC API |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |