re-opening a closed stdin?

Simon Marlow
Wed, 20 Nov 2002 12:28:44 -0000

> There's probably a really obvious answer to this, but I can't find it.
> Is there any way in GHC to reopen stdin if it has been closed?

There's no way to do this at present, except in GHCi where you can
revert CAFs to their unevaluated state.

> You may wonder why I'd want this. Well I'm writing a debugger
> for Haskell 98 (*) and my debugger wants to do some=20
> interaction on the terminal
> _after_ the user's program has run. If the user's program=20
> puts stdin into
> a closed or semi-closed state then that causes trouble for my=20
> debugger.
> What I'd like to do is close stdin after the end of the=20
> user's program,
> flush any input waiting in the buffer, then reopen it fresh=20
> for reading.
> If this can't be easily done perhaps there is another=20
> solution you can think of.

I've been thinking about duplicating/replacing Handles for a while.
Here's  a possible interface:

  -- |Returns a duplicate of the original handle, with its own buffer
  -- and file pointer.  The original handle's buffer is flushed,
  -- discarding any input data, before the handle is duplicated.
  hDuplicate :: Handle -> IO Handle

  -- |Makes the second handle a duplicate of the first handle.  The
  -- second handle will be closed first, if it is not already.
  hDuplicateTo :: Handle -> Handle -> IO ()

These are fairly straightforward to implement in GHC (I've got a working
prototype), and given these primitives you can implement the other
interfaces that have been talked about in the past
(withStdin/withStdout/withStderr, for example).

The remaining questions are:

 - Should you be allowed to duplicate a Handle which refers
   to a file opened in WriteMode?  Haskell 98 forbids having
   two Handles pointing to the same file opened for writing,
   but IMHO it's quite a reasonable thing to do.  If we don't allow
   this, then there needs to be another version of hDuplicateTo
   which invalidates the original Handle.

 - Should these be exported by System.IO?  Are there any
   fundamental problems which would make these hard or impossible to
   implement in Hugs or NHC?