Search code examples
haskellscotty

Cleaning up after a Scotty application is terminated


I have a Scotty application that listens on a Unix socket. I’d like the application to delete the socket when it exits (i.e. when I type Ctrl-C), but I’m not sure how to accomplish this. My main function looks like

main = do
    sock <- socket AF_UNIX Stream 0
    bind sock $ SockAddrUnix "/tmp/my_app.sock"
    listen sock maxListenQueue

    scottySocket def sock $ do
        ...

    removeFile "/tmp/my_app.sock"

When I type Ctrl-C the removeFile function is not called—that seems to be an interrupt that the Scotty framework does not or cannot catch. Is there any way to perform cleanup actions like this?


Solution

  • The simplest principled way probably is using bracket from Control.Exception:

    main = bracket acquireSock cleanupSock $ \(sock, _) -> do
        listen sock maxListenQueue
        scottySocket def sock $ do
            ...
        where
        -- Acquiring the resource.
        acquireSock = do
            sock <- socket AF_UNIX Stream 0
            let sockPath = "/tmp/my_app.sock"
            bind sock $ SockAddrUnix sockPath
            return (sock, sockPath)
        -- Releasing the resource.
        cleanupSock (sock, sockPath) = do
            removeFile sockPath
            close sock