Normally, Control-C sends a sigint to a program, and kills it if it’s not caught. The gnureadline library will install handlers for sigint. However, even when disabling those handlers in haskell, I still need to hit Control-C twice to kill a program. What’s going on?
import System.Console.Readline
main = do
setCatchSignals False
mainLoop
mainLoop = do
maybeLine <- readline ">"
case maybeLine of
Nothing -> putStrLn ":("
Just line -> do
putStr line
putStr " catch:"
catch <- getCatchSignals
putStrLn $ show $ catch
mainLoop
This may be related to the cooked/uncooked/rare terminal modes;
^Cdoes not always send a signal. It seems likely that readline uncooks the terminal, and thus any signals caused by keyboard input must be due to logic within readline itself; it seems plausible that it might only trigger a SIGINT on two sequential^Cs (especially since for many programs that utilise readline such as shells and REPLs, the program exiting on a single^Cwould be very annoying!).You might be able to change this behaviour by using the readline API to rebind
^Cto some of your own code that triggers a SIGINT. I haven’t used readline from Haskell, just from C, so I’m not sure exactly how you’d go about this, but the binding seems rich enough to achieve it.