
On Sat, Oct 29, 2011 at 9:36 AM, Donn Cave
The SIGINT handler looks like more of a quirk of the RTS, than a feature whose behavior you should depend on in great detail.
I looked into this some more, and found that it is indeed a quirk of the RTS -- an apparently /intentional/ one. From http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Signals: "When the interrupt signal is received, the default behaviour of the runtime is to attempt to shut down the Haskell program gracefully. It does this by calling interruptStgRts() in rts/Schedule.chttp://hackage.haskell.org/trac/ghc/browser/rts/Schedule.c (see Commentary/Rts/Scheduler#ShuttingDownhttp://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Scheduler#ShuttingDo...). If a second interrupt signal is received, then we terminate the process immediately; this is just in case the normal shutdown procedure failed or hung for some reason, the user is always able to stop the process with two control-C keystrokes" While I'm sure someone or ones meant well when designing the RTS to work in this way, I do not agree that this is sensible. It's fine for calculation or utility programs that perform one task and exit, but not for interactive programs such as shells, editors, or anything with a command line interface. IMO, handholding behavior such as this is exactly the sort of thing that risks new Haskell users coming to the conclusion that "Haskell is not intended for real programming projects" -- I know, because I nearly came to this exact conclusion while pulling my hair out trying to figure out what was going on here. Further complicating the matter is that this feature only exists in POSIX environments, i.e. not on Windows. I can use System.Posix.Signals.installHandler to catch <ctrl>C (SIGINT)
in a repeatable way, on MacOS X, so that's working as it should. If you want it to return control to the user interface, that's going to take some work - for all I know, there may be some way to hook a signal handler up with Control.Exception.catch.
Indeed, it's easy to hook up your own signal handler so that ALL keyboard interrupts have the expected behavior of throwing a UserInterrupt exception -- although I would not have thought to do this before learning that the RTS is "broken" in this regard: import Control.Exception as C import Control.Concurrent import System.Posix.Signals main = do tid <- myThreadId installHandler keyboardSignal (Catch (throwTo tid UserInterrupt)) Nothing ... -- rest of program Brian