
Thanks for the input Felipe. Felipe Almeida Lessa wrote:
On line 29, instead of
liftIO $ do mapM_ ... runResourceT $ do
Well that was because that whole block needs to run in IO.
Regarding threads, you should use resourceForkIO [1] which has a quite nicer interface.
I did read about resourceForkIO and it says: Introduce a reference-counting scheme to allow a resource context to be shared by multiple threads. Once the last thread exits, all remaining resources will be released. In my case, I don't have any resources that are shared between threads. All I have is the actual ThreadId returned by forkIO. Since that ThreadId actually isn't used explicitly anywhere (but is implicitly passed to killThread when "release releaseThread" is called). The other thing about your solution is the question of what happens to the ThreadId returned by resourceForkIO. Rewriting your solution to explicity handle the ThreadId I get: telnet :: String -> Int -> IO () telnet host port = runResourceT $ do (releaseSock, hsock) <- with (connectTo host $ PortNumber $ fromIntegral port) hClose liftIO $ mapM_ (\h -> hSetBuffering h LineBuffering) [ stdin, stdout, hsock ] tid <- resourceForkIO $ sourceHandle stdin $$ sinkHandle hsock sourceHandle hsock $$ sinkHandle stdout liftIO $ killThread tid release releaseSock The problem here is that I am not sure if the explicit killThread is actually needed and it is, I think my solution, where killThread happens automatically is actually better. If what happens within the outer call to resourceT is a long running process, your solution (in the absence of the explicit killThread) could leave threads lying around that would have been cleaned up much earlier in my soltuion. Thoughts? Erik -- ---------------------------------------------------------------------- Erik de Castro Lopo http://www.mega-nerd.com/