packages feed

hackage-server-0.5.0: Distribution/Server/Util/SigTerm.hs

{-# LANGUAGE CPP #-}
#if !(MIN_VERSION_base(4,6,0))
{-# LANGUAGE MagicHash, UnboxedTuples #-}
#endif

module Distribution.Server.Util.SigTerm (onSigTermCleanShutdown) where

import System.Posix.Signals
         ( installHandler
         , Handler(Catch)
         , softwareTermination
         )
import Control.Exception
         ( AsyncException(UserInterrupt), throwTo )
import Control.Concurrent
         ( myThreadId )
#if MIN_VERSION_base(4,6,0)
import Control.Concurrent
         ( ThreadId, mkWeakThreadId )
import System.Mem.Weak
         ( Weak )
#else
import GHC.Conc.Sync
         ( ThreadId(..) )
import GHC.Weak
         ( Weak(..) )
import GHC.IO
         ( IO(IO) )
import GHC.Exts
         ( mkWeak#, unsafeCoerce# )
#endif
import System.Mem.Weak
         ( deRefWeak )

-- | On SIGTERM, throw 'UserInterrupt' to the calling thread.
--
onSigTermCleanShutdown :: IO ()
onSigTermCleanShutdown = do
    wtid <- mkWeakThreadId =<< myThreadId
    _ <- installHandler softwareTermination
                        (Catch (cleanShutdownHandler wtid))
                        Nothing
    return ()
  where
    cleanShutdownHandler :: Weak ThreadId -> IO ()
    cleanShutdownHandler wtid = do
      mtid <- deRefWeak wtid
      case mtid of
        Nothing  -> return ()
        Just tid -> throwTo tid UserInterrupt

#if !(MIN_VERSION_base(4,6,0))
mkWeakThreadId :: ThreadId -> IO (Weak ThreadId)
mkWeakThreadId t@(ThreadId t#) = IO $ \s ->
   case mkWeak# t# t (unsafeCoerce# 0#) s of
      (# s1, w #) -> (# s1, Weak w #)
#endif