packages feed

atelier-core-0.7.2.0: src/Atelier/Signal.hs

-- | Termination handler based on Cabal's `Distribution.Client.Signal`.
-- See https://github.com/haskell/cabal/blob/aeb7dbfabad38289cb36da6fdf78acee99b69e3b/cabal-install/src/Distribution/Client/Signal.hs
module Atelier.Signal (installTerminationHandler) where

import Effectful (IOE, withSeqEffToIO)
import Effectful.Concurrent (Concurrent, myThreadId, throwTo)
import Effectful.Exception (asyncExceptionFromException, asyncExceptionToException)
import System.Posix.Signals (Handler (..), installHandler, sigTERM)
import Text.Show (Show (..))


-- | Terminated is an asynchronous exception, thrown when
-- SIGTERM is received. It's to 'kill' what 'UserInterrupt'
-- is to Ctrl-C.
data Terminated = Terminated


instance Exception Terminated where
    toException = asyncExceptionToException
    fromException = asyncExceptionFromException


instance Show Terminated where
    show Terminated = "terminated"


installTerminationHandler :: (Concurrent :> es, IOE :> es) => Eff es ()
installTerminationHandler = do
    mainThreadId <- myThreadId
    void
        $ withSeqEffToIO \unlift ->
            installHandler
                sigTERM
                (CatchOnce $ unlift $ throwTo mainThreadId Terminated)
                Nothing