System.Process

On Thu, Jun 17, 2004 at 04:33:15PM +0100, Simon Marlow wrote:
> I've now implemented the System.Process library on Windows too. It
> needs Ross Paterson's new version of the Win32 library, which can be
> found in CVS under libraries/win32.
>> While doing the Windows port I realised that parts of the interface
> didn't work out too nicely, so I have left out createPipe and
> commandToProcess from the interface. If you think it is imperative to
> have either of these, please yell.
I don't think either is imperative, but noticed that the documentation
refers to createPipe.
> Comments please... perhaps there ought to be some simpler versions of
> the general functions in this library, to cover the more common cases?
While I'm not a fan of the Maybe method of providing optional arguments,
it's hard to see any small set of simpler versions that one could devise.
Having five runProcessX functions doesn't simplify things. It's probably
simplest to let the users define simpler versions... unless you perhaps
wanted to define a runProcess analog of "system", which differs only in
that it accepts a FilePath and [String] instead of a shell command.
The simpler versions I would use would probably be:
runProcessStringInOut :: FilePath -> [String] -> String -> IO String
(last arguments is stdin and return value is stdout).
runProcessStringIn :: FilePath -> [String] -> String -> IO ExitCode
and the obvious extention
runProcessStringOut :: FilePath -> [String] -> IO String
As you can see, I always want my processes to exit. I suppose the two
which return strings could do so lazily with the process continuing to run,
but I think I'd rather have them *not* do so, since exit with failure
obviously must trigger an exception, and I'd rather get the exception
synchronously (when I can exit with "process X exited with error code Y")
rather than failing at some later date when I'm consuming a lazy string.
hGetContents is fine and dandy for files, but processes have an annoying
tendancy to fail far more often and for less obvious reasons.
Anyhow, each of the above is trivial to implement using System.Process as
given, and I see no real reason to add them (or others) to System.Process
itself.
> If there are no serious problems, this will be imported into CVS for GHC
> 6.4, and possibly future Hugs/nhc98 releases, if there aren't any
> portability problems.
Sounds great to me, although I should warn you that I haven't actually
tried any of the code...
Just to make sure I understand things... could runProcess be implemented in
terms of runInteractive as below? Not that this would be wise--I imagine it
goes the other way around--but I want to be sure that I understand how I'd
want to modify things, for example if I wanted to interactively write to a
process, but have its output logged straight to a file.
runProcess c as menv (Just inh) (Just outh) (Just errh) =
do (iinh, iouth, ierrh, ph) <- runInteractiveProcess c as menv
instr <- hGetContents inh
outstr <- hGetContents iouth
errstr <- hGetContents ierrh
forkIO $ do hPutStr outh outstr
hClose outh
forkIO $ do hPutStr errh errstr
hClose errh
forkIO $ do hPutStr iinh instr
hClose iinh
return ph
this hGetContents followed by forkIO hPutStr hClose seems like it ought to
be relatively common. Is there a simple command to just connect a read
handle to a write handle? That would be a useful function, I imagine... and
could be implemented much more efficiently if the contents weren't
converted to a lazy String in between.
--
David Roundy
http://www.abridgegame.org