7

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
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
archgoon
  • 1,538
  • 2
  • 14
  • 19
  • 2
    This may be related to cooked/uncooked/rare terminal modes; `^C` does not always send a signal. It could be that readline causes a SIGTERM only on two sequential `^C`s. – ehird Dec 23 '11 at 19:47
  • Oh, interesting. I hadn't known that about terminal modes. I'll check and see if readline does something with that. Thank you. – archgoon Dec 23 '11 at 19:49
  • I've expanded it slightly into an answer :) – ehird Dec 23 '11 at 19:59

1 Answers1

8

This may be related to the cooked/uncooked/rare terminal modes; ^C does 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 ^C would be very annoying!).

You might be able to change this behaviour by using the readline API to rebind ^C to 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.

ehird
  • 40,602
  • 3
  • 180
  • 182