我想为我的 web 应用程序实现一个“正常关闭”命令(与我的第一直觉相反,即只是要求人们终止该进程)
我的前两次尝试包括
liftIO exitSuccess
E.yield (responseLBS statusOK [G.contentType "text/plain"] "") E.EOF
两者都只是愉快地将结果返回给客户并继续倾听。应用程序可以做些什么来杀死服务器吗?这是否是一件合理的事情呢?
我承认我对 iteratee 没有很强的了解,只知道我可以使用我的输入并且 Iteratee 是一个 MonadIO 实例。
- 使用MVar。阻塞主线程,直到 MVar 收到信号,然后清理并退出。
- Call
exitImmediately
。拆除进程的最快方法之一,而且调试起来也非常烦人。我不相信终结器/括号/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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)