Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write Ctrl-C handler in Haskell?

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?

like image 718
Rogach Avatar asked Nov 18 '12 15:11

Rogach


1 Answers

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.

like image 109
Daniel Fischer Avatar answered Oct 04 '22 21:10

Daniel Fischer