
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 file?
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