I played with the conduit-extra UNIX package, which basically makes it easy to create a server using UNIX domain sockets, in particular using runUnixServer funciton .
The problem is that after the function exists, it does not clear the socket file, which means that it must be cleaned manually. Here is a simple example that basically creates an echo server.
main :: IO () main = do let settings = serverSettings "foobar.sock" runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
I searched Google a bit and found that the right way to handle resources here is to use resourcet . Although the problem is that most of the APIs in the resources expect me to runUnixSever this resource myself, which is not the case with runUnixSever , which does not return anyhting.
At first I decided to use register to register a function that deletes the file, e.g.
main :: IO () main = runResourceT $ do register $ removeLink "foobar.sock" let settings = serverSettings "foobar.sock" liftIO $ runUnixServer settings (\ad -> (appSource ad) $$ (appSink ad))
There is a problem with this approach, although at least the documentation for allocate says:
This is almost identical to invoking the distribution and registration of the release action, but it correctly handles the masking of asynchronous exceptions.
Does this mean that register by itself does not handle asynchronous exceptions? If so, it could be a problem when one of the handlers generated by runUnixServer (docs say it spawns a thread for each client) causes an error?
The third and final solution I came across is to use allocate to make sure that asynchronous exceptions are handled correctly (I'm not sure if this is really necessary in this case).
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))
But is this really the best solution? Since I am creating a value that I will never use (return 1) , and then using the const function to ignore that value in the finalizer.
resources haskell sockets conduit
Jakub arnold
source share