Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Spawn subprocesses and interact with them using Pipes
The interface in this module deliberately resembles the interface in System.Process. However, one consequence of this is that you will not want to have unqualified names from this module and from System.Process in scope at the same time.
As in System.Process, you create a subprocess by creating a
CreateProcess
record and then applying a function to that
record. Unlike System.Process, you use functions such as
pipeInput
or pipeInputOutput
to specify what streams you want
to use a Proxy
for and what streams you wish to be Inherit
ed
or if you want to UseHandle
. You then send or receive
information using the returned Proxy
.
Use the -threaded
GHC option when compiling your programs or
when using GHCi. Internally, this module uses
waitForProcess
from the System.Process module;
it's also quite likely that you will use this function when you
write code using this library. As the documentation for
waitForProcess
states, you must use the -threaded
option to
prevent every thread in the system from suspending when you use
waitForProcess
. So, if your program experiences deadlocks, be
sure you used the -threaded
option.
This module relies on the Pipes, Pipes.Safe, and System.Process modules. You will want to have basic familiarity with what all of those modules do before using this module. It uses Control.Concurrent.Async and Pipes.Concurrent behind the scenes; you don't need to know how these work unless you're curious.
All communcation with subprocesses is done with strict
ByteString
s. If you are dealing with textual data, the text
library has functions to convert a ByteString
to a Text
; you
will want to look at Data.Text.Encoding
.
Nobody would mistake this module for a shell; nothing beats the shell as a language for starting other programs, as the shell is designed for that. This module allows you to perform simple streaming with subprocesses without leaving the comfort of Haskell. Take a look at the README.md file, which is distributed with the tarball or is available at Github at
https://github.com/massysett/pipes-cliff
There you will find references to other libraries that you might find more useful than this one.
For some simple examples, consult Pipes.Cliff.Examples.
- data NonPipe
- data CreateProcess = CreateProcess {}
- procSpec :: String -> [String] -> CreateProcess
- pipeNone :: MonadSafe m => NonPipe -> NonPipe -> NonPipe -> CreateProcess -> m ProcessHandle
- pipeInput :: (MonadSafe mi, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Consumer ByteString mi (), ProcessHandle)
- pipeOutput :: (MonadSafe mi, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Producer ByteString mi (), ProcessHandle)
- pipeError :: (MonadSafe mi, MonadSafe m) => NonPipe -> NonPipe -> CreateProcess -> m (Producer ByteString mi (), ProcessHandle)
- pipeInputOutput :: (MonadSafe mi, MonadSafe mo, MonadSafe m) => NonPipe -> CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), ProcessHandle)
- pipeInputError :: (MonadSafe mi, MonadSafe mo, MonadSafe m) => NonPipe -> CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), ProcessHandle)
- pipeOutputError :: (MonadSafe mi, MonadSafe mo, MonadSafe m) => NonPipe -> CreateProcess -> m (Producer ByteString mi (), Producer ByteString mo (), ProcessHandle)
- pipeInputOutputError :: (MonadSafe mi, MonadSafe mo, MonadSafe me, MonadSafe m) => CreateProcess -> m (Consumer ByteString mi (), Producer ByteString mo (), Producer ByteString me (), ProcessHandle)
- conveyor :: Effect (SafeT IO) () -> SafeT IO ()
- background :: MonadSafe m => IO a -> m (Async a)
- waitForProcess :: MonadIO m => ProcessHandle -> m ExitCode
- waitForThread :: MonadIO m => Async a -> m a
- module Pipes
- module Pipes.Safe
- module System.Exit
- module System.Process
Specifying a subprocess's properties
How will the subprocess get its information for this stream?
data CreateProcess Source
Like CreateProcess
in System.Process,
this gives the necessary information to create a subprocess. All
but one of these fields is also present in
CreateProcess
, and they all have the same meaning;
the only field that is different is the quiet
field.
CreateProcess | |
|
:: String | The name of the program to run, such as |
-> [String] | Command-line arguments |
-> CreateProcess |
Create a CreateProcess
record with default settings. The
default settings are:
- a raw command (as opposed to a shell command) is created
- the current working directory is not changed from the parent process
- the environment is not changed from the parent process
- the parent's file descriptors (other than standard input, standard output, and standard error) are inherited
- no new process group is created
delegate_ctlc
isFalse
quiet
isFalse
Creating processes
Each of these functions creates a process. The process begins
running immediately in a separate process while your Haskell program
continues concurrently. A function is provided for each possible
combination of standard input, standard output, and standard error.
Use the NonPipe
type to describe what you want to do with streams
you do NOT want to create a stream for. For example, to create a
subprocess that does not create a Pipe for any of the standard
streams, use pipeNone
. You must describe what you want done with
standard input, standard output, and standard error. To create a
subprocess that creates a Pipe for standard input and standard
output, use pipeInputOutput
. You must describe what you want done
with standard error. A Producer
is returned for standard output
and a Consumer
for standard input.
Do NOT attempt to use any of the resources created by this function
outside of the MonadSafe
computation. The
MonadSafe
computation will destroy all resources when
the MonadSafe
computation is complete. This means that
all these functions are exception safe: all resources--threads and
processes included--are destroyed when the MonadSafe
computation is complete, even if an exception is thrown. However,
this does mean that you need to stay in the MonadSafe
computation if you need to keep a resource around. waitForProcess
can be handy for this. All functions in this section return a
ProcessHandle
for use with waitForProcess
.
Each Proxy
automatically destroys associated file handles and other
behind-the-scenes resources after its computation finishes running;
that's why the monad stack of each Proxy
must contain a
MonadSafe
. For an example of how to deal with the
MonadSafe
class, consult Pipes.Cliff.Examples.
:: MonadSafe m | |
=> NonPipe | Standard input |
-> NonPipe | Standard output |
-> NonPipe | Standard error |
-> CreateProcess | |
-> m ProcessHandle |
Do not create any Proxy
to or from the process.
:: (MonadSafe mi, MonadSafe m) | |
=> NonPipe | Standard output |
-> NonPipe | Standard error |
-> CreateProcess | |
-> m (Consumer ByteString mi (), ProcessHandle) | A |
Create a Consumer
for standard input.
:: (MonadSafe mi, MonadSafe m) | |
=> NonPipe | Standard input |
-> NonPipe | Standard error |
-> CreateProcess | |
-> m (Producer ByteString mi (), ProcessHandle) | A |
Create a Producer
for standard output.
:: (MonadSafe mi, MonadSafe m) | |
=> NonPipe | Standard input |
-> NonPipe | Standard output |
-> CreateProcess | |
-> m (Producer ByteString mi (), ProcessHandle) | A |
Create a Producer
for standard error.
:: (MonadSafe mi, MonadSafe mo, MonadSafe m) | |
=> NonPipe | Standard error |
-> CreateProcess | |
-> m (Consumer ByteString mi (), Producer ByteString mo (), ProcessHandle) | A |
:: (MonadSafe mi, MonadSafe mo, MonadSafe m) | |
=> NonPipe | Standard output |
-> CreateProcess | |
-> m (Consumer ByteString mi (), Producer ByteString mo (), ProcessHandle) | A |
:: (MonadSafe mi, MonadSafe mo, MonadSafe m) | |
=> NonPipe | Standard input |
-> CreateProcess | |
-> m (Producer ByteString mi (), Producer ByteString mo (), ProcessHandle) | A |
:: (MonadSafe mi, MonadSafe mo, MonadSafe me, MonadSafe m) | |
=> CreateProcess | |
-> m (Consumer ByteString mi (), Producer ByteString mo (), Producer ByteString me (), ProcessHandle) | A |
Background operations
Often it is necessary to run threads in the background; in addition, all subprocesses run in the background. These functions allow you to launch threads in the background and to wait on background threads and subprocesses.
conveyor :: Effect (SafeT IO) () -> SafeT IO () Source
Runs in the background an effect, typically one that is moving
data from one process to another. For examples of its usage, see
Pipes.Cliff.Examples. The associated thread is killed when the
SafeT
computation completes.
background :: MonadSafe m => IO a -> m (Async a) Source
Runs a thread in the background. Initializes a finalizer that
will cancel the thread if it is still running when the
MonadSafe
computation completes.
waitForProcess :: MonadIO m => ProcessHandle -> m ExitCode Source
A version of waitForProcess
with an overloaded
MonadIO
return type.
waitForThread :: MonadIO m => Async a -> m a Source
A version of wait
with an overloaded
MonadIO
return type. Allows you to wait for the return value of
threads launched with background
. If the thread throws an
exception, waitForThread
will throw that same exception.
Re-exports
- Pipes reexports all bindings
- Pipes.Safe reexports
runSafeT
- System.Exit reexports all bindings
- System.Process reexports
ProcessHandle
module Pipes
module Pipes.Safe
module System.Exit
module System.Process