の UNIX パッケージをいじってみました。これは基本的に、UNIX ドメイン ソケットを使用して、特にfuncitonconduit-extraを使用してサーバーを簡単に作成できるようにします。runUnixServer
問題は、関数が存在した後、ソケット ファイルをクリーンアップしないことです。つまり、手動でクリーンアップする必要があります。基本的にエコーサーバーを作成する簡単な例を次に示します。
main :: IO ()
main = do
let settings = serverSettings "foobar.sock"
runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
少しグーグルで調べたところ、ここでリソースを処理する正しい方法は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))
ただし、少なくともドキュメントに記載されている限り、このアプローチには問題がありallocateます。
これは、割り当てを呼び出してから解放アクションを登録するのとほぼ同じですが、非同期例外のマスキングを適切に処理します。
これはregister、それ自体では非同期例外を処理しないということですか? もしそうなら、それによって生成されたハンドラーの1つがrunUnixServerエラーを発生させたときに問題になる可能性がありますか?
私が思いついた 3 番目の最終的な解決策は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))
しかし、これは本当に最善の解決策でしょうか? 私は決して使用しない値を作成しているので、ファイナライザーでその値を無視する関数を(return 1)使用しています。const