I tried the following approach:
import System.Exit
import System.Posix.Signals
import Control.Concurrent (threadDelay)
main :: IO ()
main = do
installHandler
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.