Ticket #4162 (new bug)
GHC API messes up signal handlers
| Reported by: | jcpetruzza | Owned by: | |
|---|---|---|---|
| Priority: | low | Milestone: | 7.6.2 |
| Component: | GHC API | Version: | 6.12.3 |
| Keywords: | Cc: | chowells79@… | |
| Operating System: | Unknown/Multiple | Architecture: | Unknown/Multiple |
| Type of failure: | None/Unknown | Difficulty: | |
| Test Case: | Blocked By: | ||
| Blocking: | Related Tickets: |
Description
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).
