packages feed

reflex-vty-1.2.0.0: src/Reflex/Vty/Host/Signal.hs

{-# LANGUAGE CPP #-}

-- |
-- Module: Reflex.Vty.Host.Signal
-- Description: Cross-platform OS signal handling for reflex-vty.
module Reflex.Vty.Host.Signal
  ( AppSignal (..)
  , installAppSignalHandlers
  ) where

import Foreign.C.Types (CInt)

#if defined(mingw32_HOST_OS)
import Control.Monad (void)
import qualified GHC.ConsoleHandler as Console
#else
import Control.Monad (forM_)
import System.Posix.Signals (Handler (Catch), installHandler, sigHUP, sigINT, sigTERM)
#endif

-- | An OS-level signal delivered to a running application.
--
--   * 'AppSignal_Interrupt': POSIX @SIGINT@ or Windows @ControlC@
--   * 'AppSignal_Terminate': POSIX @SIGTERM@ or Windows @Shutdown@
--   * 'AppSignal_Hangup': POSIX @SIGHUP@ or Windows @Close@ or Windows @Logoff@
--
-- All other signals can be shoved into the 'AppSignal_Platform' escape hatch.
data AppSignal
  = AppSignal_Interrupt
  | AppSignal_Terminate
  | AppSignal_Hangup
  | AppSignal_Platform CInt
  deriving (Eq, Show)

-- | Install handlers for OS signals
installAppSignalHandlers :: (AppSignal -> IO ()) -> IO ()

#if defined(mingw32_HOST_OS)

-- via 'GHC.ConsoleHandler'
installAppSignalHandlers fire =
  void $ Console.installHandler $ Console.Catch (fire . toAppSignal)
  where
    toAppSignal :: Console.ConsoleEvent -> AppSignal
    toAppSignal ev = case ev of
      Console.ControlC -> AppSignal_Interrupt -- Ctrl-C: same intent as SIGINT.
      Console.Break -> AppSignal_Interrupt -- Ctrl-Break: closest to an interrupt.
      Console.Close -> AppSignal_Hangup -- console window closed: terminal going away.
      Console.Logoff -> AppSignal_Hangup -- user logging off: session going away.
      Console.Shutdown -> AppSignal_Terminate -- system shutting down: clean termination.

#else

installAppSignalHandlers fire =
  forM_ signals $ \(sig, appSignal) ->
    installHandler sig (Catch (fire appSignal)) Nothing
  where
    signals =
      [ (sigINT, AppSignal_Interrupt)
      , (sigTERM, AppSignal_Terminate)
      , (sigHUP, AppSignal_Hangup)
      ]

#endif