Jak*_*old 7 sockets resources haskell conduit
我一直在使用conduit-extraUNIX软件包,它基本上允许使用UNIX域套接字轻松创建服务器,特别是使用runUnixServer函数.
问题是在函数存在之后它不会清理套接字文件,这意味着它需要手动清理.这是一个简单的例子,它基本上创建了一个echo服务器.
main :: IO ()
main = do
let settings = serverSettings "foobar.sock"
runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
Run Code Online (Sandbox Code Playgroud)
我已经谷歌了一下,发现在这里处理资源的正确方法是使用resourcet包.虽然问题在于资源中的大多数API都希望我自己分配资源runUnixSever,但事实并非如此,这并不会给任何人带来任何影响.
起初我以为我可以使用register,注册一个删除文件的函数,如下所示
main :: IO ()
main = runResourceT $ do
register $ removeLink "foobar.sock"
let settings = serverSettings "foobar.sock"
liftIO $ runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
Run Code Online (Sandbox Code Playgroud)
但是这种方法存在问题,至少就文档allocate说:
这与调用分配然后注册释放操作几乎完全相同,但这可以正确处理异步异常的屏蔽.
这是否意味着它register本身不处理异步异常?如果是这样,当由runUnixServer(文档说它为每个客户端生成一个线程)产生的处理程序之一引发错误时,这可能是一个问题吗?
我想出的第三个也是最后一个解决方案是使用allocate,以确保正确处理异步异常(我不确定在这种情况下是否真的有必要).
main :: IO ()
main = runResourceT $ do
allocate (return 1) (const $ removeLink "foobar.sock")
let settings = serverSettings "foobar.sock"
liftIO $ runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
Run Code Online (Sandbox Code Playgroud)
但这真的是最好的解决方案吗?因为我正在创建一个我永远不会使用的值,(return 1)然后使用const函数来忽略终结器中的值.
在解决resourcet问题之前:
resourcet在这种情况下不需要.你可以使用这个finally功能,例如runUnixServer settings (\ad -> ...)最后removeLink "foobar.sock".也就是说,您的初始代码register很好.我看到的唯一问题是如果在foobar.sock创建之前抛出异常,尽管我的finally解决方案也容易受到攻击.
有关allocate vs register的注释与代码如下所示:
handle <- openFile fp ReadMode
register $ hClose handle
Run Code Online (Sandbox Code Playgroud)
此代码容易受到在openFile和register调用之间抛出的异步异常的影响.既然你没有像这样分配资源,那register很好.
| 归档时间: |
|
| 查看次数: |
508 次 |
| 最近记录: |