- Используйте MVar.Блокируйте основной поток до тех пор, пока MVar не получит сигнал, затем очистите и выйдите.
- Вызов
exitImmediately
.Один из самых быстрых способов снести процесс, а также ужасно раздражает отладку.Я не верю, что блоки finalizer / brackets / finally будут вызываться по пути вниз, в зависимости от вашего приложения это может привести к повреждению состояния. - Бросить исключение в основной поток.
Warp.run
не перехватывает исключения, поэтому это работает, позволяя обработчику исключений по умолчанию в главном потоке (и только в основном потоке) завершать процесс.
Как уже упоминалось, использованиеMVar, вероятно, лучший вариант.Я включил другие ради полноты, но у них есть свое место.throwTo
в некоторой степени используется в базовой библиотеке, и я работал над несколькими приложениями, которые используют эквивалент C * exitImmediately
: exit()
, хотя я не запускал никаких приложений на Haskell, использующих этот метод.
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
module Main (main) where
import Control.Concurrent (MVar, ThreadId, forkIO, myThreadId, newEmptyMVar, putMVar, takeMVar)
import Control.Exception (Exception, throwTo)
import Control.Monad.Trans (liftIO)
import Data.ByteString (ByteString)
import Data.Data (Data, Typeable)
import Data.Enumerator (Iteratee)
import Network.HTTP.Types
import Network.Wai as Wai
import Network.Wai.Handler.Warp as Warp
import System.Exit (ExitCode (ExitSuccess))
import System.Posix.Process (exitImmediately)
data Shutdown = Shutdown deriving (Data, Typeable, Show)
instance Exception Shutdown
app :: ThreadId -> MVar () -> Request -> Iteratee ByteString IO Response
app mainThread shutdownMVar Request{pathInfo = pathInfo} = do
liftIO $ case pathInfo of
["shutdownByThrowing"] -> throwTo mainThread Shutdown
["shutdownByMVar"] -> putMVar shutdownMVar ()
["shutdownByExit"] -> exitImmediately ExitSuccess
_ -> return ()
return $ responseLBS statusOK [headerContentType "text/plain"] "ok"
main :: IO ()
main = do
mainThread <- myThreadId
shutdownMVar <- newEmptyMVar
forkIO $ Warp.run 3000 (app mainThread shutdownMVar)
takeMVar shutdownMVar