Hi,

Einar Wolfgang Karlsen writes:
> 
> Consider the following Concurrent Haskell program where a reader
> thread is forked off to wait for input over the reading end of a 
> pipe. The main thread attempts after a while to close this 
> file descriptor.
> 
> module Main (
>       main    
>       ) where
> 
> import Concurrent
> import Posix
> import PosixUtil
> import GlaExts
> 
> main = do {
>       (r,w) <- createPipe;
>       forkIO (reader r);
>       threadDelay 100000;
>       print "closing pipes";
>       try (fdClose r);
>       try (fdClose w);
>       threadDelay 100000;
>       print "main thread done";
>       return ()
> } where reader r = do {threadWaitRead (fdToInt r); return ()}
>       fdToInt :: Fd -> Int
>       fdToInt (FD# fd#) = I# fd# 
>       try c = catch (c >>= return . Right ) (return . Left) 
> 

Thanks for the tip, I've added fdToInt to PosixUtil (try is provided
by IO though.)

> The outcome of running this little program is that it aborts with: 
> 
> ewk@hydra% test1
> "closing pipes"
> AwaitEvent: select failed
> ewk@hydra% 
> 
> Personally I would find application development much easier if (1) the
> reader thread was simply garbage collected or (2) the suspended call to
> threadWaitRead failed with an error fdClosed or something like that.
> (2) is my personal choice since it would allow the reader thread to do
> some meaningful work in response to the error, but (1) is ok as well.
> However, aborting the whole program is far too extreme for my taste and
> the kind of applications that I develop (Unix client-server applications).
> 

Hmm..there's a couple of things going on here:

- The Concurrent Haskell IO implementation isn't non-blocking.
- Hence you have to drop down to the level of file descriptors
  and threadWaitRead&Write to work.

We're reluctant to add support at the level of file descriptors for
what you're suggesting, instead you should be able to write:


hCreatePipe :: IO (Handle, Handle)

main = do {
        (r,w) <- hCreatePipe;
        forkIO (reader r);
        threadDelay 100000;
        print "closing pipes";
        try (hClose r);
        try (hClose w);
        threadDelay 100000;
        print "main thread done";
        return ()
 } where reader r = do {hReady r; return ()}

using a non-blocking version of IO, that implicitly would deal with
the closing of handles that other threads are waiting for I/O on.

Are there cases where a Concurrent Haskell friendly implementation of
IO would fail to deliver the functionality you want?

--Sigbjorn

Reply via email to