Getting the file descriptor of a handle, without closing it

Simon Marlow marlowsd at
Mon Mar 12 12:31:27 CET 2012

On 11/03/2012 01:31, Volker Wysk wrote:
> Hi
> This is an addition to my previous post.
> This modified version of main seems to work:
> main = do
>     fd<- unsafeWithHandleFd stdin return
>     putStrLn ("stdin: fd = " ++ show fd)
>     fd<- unsafeWithHandleFd stdout return
>     putStrLn ("stdout: fd = " ++ show fd)
> The way I understand it, unsafeWithHandleFd's job is to keep a reference to
> the hande, so it won't be garbage collected, while the action is still
> running. Garbage collecting the handle would close it, as well as the
> underlying file descriptor, while the latter is still in use by the action.
> This can't happen as long as use of the file descriptor is encapsulated in the
> action.
> This encapsulation can be circumvented by returning the file descriptor, and
> that's what the modified main function above does. This should usually never be
> done.

Right.  The problem with this:

     -- Blocks
    unsafeWithHandleFd stdout $ \fd ->
       putStrLn ("stdout: fd = " ++ show fd)

is that unsafeWithHandleFd is holding the lock on stdout, while you try 
to write to it with putStrLn.  The implementation of unsafeWithHandleFd 
could probably be fixed to avoid this - as you say, all it needs is to 
hold a reference to the Handle until the function has returned.  The 
usual way to "hold a reference" to something is to use touch#.

> However, I want to use it with stdin, stdout and stderr, only.

Is there some reason you can't just use 0, 1, and 2?

 > These three
> should never be garbage collected, should they? I think it would be safe to
> use unsafeWithHandleFd this way. Am I right?

I wouldn't do that, but you're probably right that it is safe right now. 
(but no guarantees that it will continue to work for ever.)


More information about the Glasgow-haskell-users mailing list