How to write Ctrl-C handler in Haskell?

haskell, signals

Solution

From the docs of `installHandler`:

a handler is installed which will invoke action in a new thread when (or shortly after) the signal is received.

and `exitWith:`

Note: in GHC, exitWith should be called from the main program thread in order to exit the process. When called from another thread, exitWith will throw an ExitException as normal, but the exception will not cause the process itself to exit.

So an `exitSuccess` handler doesn't end the process, and that's expected (although unexpected ;) behaviour.

If you want immediate action,

import System.Exit
import System.Posix.Signals
import Control.Concurrent

main :: IO ()
main = do
  tid <- myThreadId
  installHandler keyboardSignal (Catch (killThread tid)) Nothing
  threadDelay (1000000000)

kills the thread immediately upon receiving the signal.

Less drastic, if you want a successful exit, would be

import System.Exit
import System.Posix.Signals
import Control.Concurrent
import qualified Control.Exception as E

main :: IO ()
main = do
  tid <- myThreadId
  installHandler keyboardSignal (Catch (E.throwTo tid ExitSuccess)) Nothing
  threadDelay (10000000)

I think it will also work reliably, but I'm not entirely sure.

Problem

I tried the following approach: ``` import System.Exit import System.Posix.Signals import Control.Concurrent (threadDelay) main :: IO () main = do installHandler keyboardSignal (Catch (do exitSuccess)) Nothing threadDelay (1000000000) ``` But it only outputs: ``` ^CTest.hs: ExitSuccess ``` on `Ctrl-C`, instead of exiting. How should I do it properly?

Original source