- MVarを使用します。MVarが通知されるまでメインスレッドをブロックしてから、クリーンアップして終了します。
- を呼び出し
exitImmediately
ます。プロセスを破棄するための最速の方法の1つであり、デバッグするのも非常に面倒です。アプリケーションによっては、状態が破損する可能性があるため、ファイナライザー/ブラケット/ファイナリーブロックが途中で呼び出されるとは思いません。
- メインスレッドに例外をスローします。
Warp.run
は例外をキャッチしないため、これはメインスレッド(およびメインスレッドのみ)のデフォルトの例外ハンドラーがプロセスを終了できるようにすることで機能します。
他の人が述べているように、MVarを使用することがおそらく最良のオプションです。完全を期すために他のものを含めましたが、それらには場所があります。はベースライブラリでいくらか使用されており、Cと同等の:throwTo
を使用するいくつかのアプリケーションに取り組んできましたが、このメソッドを使用するHaskellアプリはありません。exitImmediately
exit()
{-# 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