[Haskell-cafe] File handles and pipes
donn at avvanta.com
Sun Oct 19 03:59:06 EDT 2008
Quoth "Stephen Hicks" <sdh33 at cornell.edu>:
> In general, given a handful of system calls (and/or
> read/write handles), is there a way to combine them all together?
Well, sure - if I understand what you mean. Not "Handles", in the
sense of a Haskell library construct, but UNIX pipes and processes
are reasonably simple to work with in a general purpose programming
I'm sorry to say the following isn't real code, since GHC doesn't
run on the platform I'm using to write this mail, but I hope it will
serve to demonstrate the principles using bare UNIX system calls,
and that it doesn't contain any serious errors.
forkProcess $ do -- pipe tail
(pa0, pa1) <- createPipe
-- Command exec'd in this fork reads from this pipe,
-- so dup 0 (input) from pipe input fd. Both ends of
-- pipe will be inherited by child forks.
dupTo pa0 0
forkProcess $ do -- first pipe head
-- Command exec'd in this fork writes to parent's pipe.
dupTo pa1 1
-- Close parent's pipe so fds won't be inherited by
-- next fork.
forkProcess $ execFile "/bin/df" ... -- second pipe head
execFile "/bin/df" ...
-- Close own pipe write end, so child process exit(s) will cause EOF
execFile "/usr/bin/sort" ...
Input, output and error are file descriptors 0, 1 and 2,
by definition (pronounced "unit 0", etc.)
dupTo (UNIX system call dup2()) duplexes an I/O stream, so
"dupTo p0 0" sets up a pipe for a standard UNIX command
that reads from unit 0.
Reads from the pipe's read fd will either return data or block,
until exit of the *last* process with the pipe's write end open.
Hence the importance of closing the write end of your own pipe,
and not letting pipe fds "leak" into child processes.
Donn Cave, donn at avvanta.com
More information about the Haskell-Cafe