18

Webアプリケーションに「グレースフルシャットダウン」コマンドを実装したい(プロセスを強制終了するように人々に依頼するという私の最初の本能とは対照的)

私の最初の2つの試みは

  1. liftIO exitSuccess
  2. E.yield (responseLBS statusOK [G.contentType "text/plain"] "") E.EOF

どちらも元気に結果をクライアントに返し、聞き続けました。サーバーを強制終了するためにアプリケーションでできることはありますか?これはやりたいことでも合理的なことですか?

私はiterateeについてあまり深く理解しておらず、入力を消費できること、およびIterateeがMonadIOインスタンスであることを知っているだけで十分だと告白します。

4

1 に答える 1

13
  1. MVarを使用します。MVarが通知されるまでメインスレッドをブロックしてから、クリーンアップして終了します。
  2. を呼び出しexitImmediatelyます。プロセスを破棄するための最速の方法の1つであり、デバッグするのも非常に面倒です。アプリケーションによっては、状態が破損する可能性があるため、ファイナライザー/ブラケット/ファイナリーブロックが途中で呼び出されるとは思いません。
  3. メインスレッドに例外をスローします。Warp.runは例外をキャッチしないため、これはメインスレッド(およびメインスレッドのみ)のデフォルトの例外ハンドラーがプロセスを終了できるようにすることで機能します。

他の人が述べているように、MVarを使用することがおそらく最良のオプションです。完全を期すために他のものを含めましたが、それらには場所があります。はベースライブラリでいくらか使用されており、Cと同等の:throwToを使用するいくつかのアプリケーションに取り組んできましたが、このメソッドを使用するHaskellアプリはありません。exitImmediatelyexit()

{-# 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 
于 2011-11-17T05:59:33.697 に答える