If I understand this correctly, spin should be written as:
spin = do
block $ do
(t, _) <- accept s
unblock (forkIO $ doStuff t) `finally` sClose t
spin
I think the `finally` portion should be done in the forked process context. Otherwise once the process is forked, the socket gets closed by the parent process. Something more along the lines of:
unblock (forkIO $ doStuff t `finally` sClose t)
--