Proposal: overhaul System.Process

Frederik Eaton frederik at
Thu Jun 19 19:20:52 EDT 2008

David Roundy-2 wrote:
> On Wed, Jun 18, 2008 at 04:22:24PM -0700, Frederik Eaton wrote:
>> David Roundy-2 wrote:
>> > No, createProcess is more low-level than the previous interface, which
>> > is why it can't be implemented using the previous interfaces, but
>> > rather they can be implemented using createProcess.  Which is why they
>> > can be deprecated, although I'd hope they won't be removed for at
>> > least a couple more ghc releases after createProcess is introduced.
>> In what way is 'createProcess' more low-level than the previous
>> interfaces?
> The easiest sense in which it's more low-level is that the previous
> two commands runProcess and runInteractiveProcess can both be
> implemented using createProcess, but not the other way around.
> New API: (a subset thereof, actually)
> createProcess :: CreateProcess
>               -> IO (Maybe Handle, Maybe Handle, Maybe Handle,
> ProcessHandle)
> data CreateProcess = CreateProcess {
>   cmdspec :: CmdSpec
>   cwd :: (Maybe FilePath)
>   env :: (Maybe [(String, String)])
>   std_in :: StdStream
>   std_out :: StdStream
>   std_err :: StdStream
>   close_fds :: Bool
> }
> Old API:
> runProcess :: FilePath -> [String] -> Maybe FilePath
>            -> Maybe [(String, String)]
>            -> Maybe Handle -> Maybe Handle -> Maybe Handle
>            -> IO ProcessHandle
> runInteractiveProcess :: FilePath -> [String]
>                       -> Maybe FilePath -> Maybe [(String, String)]
>                       -> IO (Handle, Handle, Handle, ProcessHandle)
> In the old API, you are required to either use preexisting handles for
> each of stdin/stdout/stderr (possibly allowing the child process to
> inherit some or all of them), *or* create new pipes for all three.
> You might consider trying to implement runInteractiveProcess using
> runProcess (you certainly can't do the opposite) by setting up pipes
> and passing them to runProcess, but there's no portable function that
> can be used to do this, so you'd be out of luck.  You'd be stuck doing
> what darcs has long done:  write to temporary files on disk, which is
> totally braindead.
> createProcess is (so far as I can tell) the lowest-level *portable*
> Haskell API for spawning processes that has yet been proposed, in the
> sense that there are no other proposed functions that could be used to
> implement createProcess, and no other proposed functions that cannot
> be implemented using createProcess.

It sounds like we are confusing "low-level" with "powerful". I don't know
enough about portability and the constraints imposed by portability to
comment on what else could be done, but the fact that we keep changing
interfaces for process execution suggests to me that the existing interfaces
have not been low-level enough. For instance, why can't we create a pipe
independently of a process? What about creating pipes to file descriptors
other than standard input/output/error? If we had good Haskell interfaces to
OS-level primitives, as John Meacham suggested, then we could build
something that tries to be a "greatest common denominator" on top of these.
I am skeptical that the result would look very much like 'createProcess',
for instance doesn't Windows have a concept of file descriptors other than
standard input/output/error? I suppose that I can always use
System.Posix.Process, though, and hope that it doesn't change too much...


View this message in context:
Sent from the Haskell - Libraries mailing list archive at

More information about the Libraries mailing list