[Haskell-cafe] Re: I/O interface

Ben Rudiak-Gould Benjamin.Rudiak-Gould at cl.cam.ac.uk
Wed Jan 12 18:23:51 EST 2005

Simon Marlow wrote:

 >I assumed that dup()'ing file descriptors would be enough to produce
 >separate file pointers, but no.

Question (for qrczak or the group at large): is there *any* way to get, 
without an exploitable race condition, two filehandles to the same file 
which don't share a file pointer? Is there any way to pass a filehandle 
as stdin to an untrusted/uncooperative child process in such a way that 
the child can't interfere with your attempts to (say) append to the same 

 >So you can only safely make a single stream from a File.

I think we just need more kinds of streams. With regard to file-backed 
streams, there are three cases:

  1. We open a file and use it in-process.
  2. We open a file and share it with child processes.
  3. We get a handle at process startup which happens to be a file.

In case 1 there are no problems, and we should support multiple streams 
on such files.

In case 2 we could avoid OS problems by creating a pipe and managing our 
end in-process. This would allow attaching child processes to arbitrary 
streams (e.g. one with a gzip filter on it, if we ever implement such a 
thing). In certain cases it might be possible to rely on OS support, but 
it seems fragile (if we create two child processes tied to two streams 
on the same file).

Case 3 is the most interesting. In an ideal world I would argue for 
treating stdin/out/err simply as streams, but that's not practical. 
Failing that, if we have pread and pwrite, we should provide two 
versions of stdin/out/err, one of type InputStream/OutputStream and the 
other of type Maybe File. We can safely layer other streams on top of 
these files (if they exist) without interfering with the stream 
operation. The only thing we can't do with this interface is screw up 
the parent process by seeking the inherited handles. Can anyone come up 
with a case for allowing that in the high-level library? It can always 
be done through System.Posix.

If we don't have pread and pwrite, we're screwed, but so is every other 
application on this badly broken OS. If we punt on the interference 
problem, we can implement a pread and pwrite that are atomic within our 
process, and go from there. We're no worse off than anyone else here.

Unfortunately, Win9x lacks pread and pwrite. But anyone running Win9x is 
clearly willing to deal with much worse problems than this.

 >Making multiple streams would require re-opening the file for each 
subsequent one,

Windows Server 2003 has ReOpenFile, but no prior version of Win32 can do 
this, as far as I know. I don't know the *ix situation.

With ReOpenFile we could implement a lot more of my original proposal, 
including a File type that really denoted a file (instead of a file 
access path).

-- Ben

More information about the Haskell-Cafe mailing list