The Process package provides support for handling Unix style processes. For each external process that you want to handle, you need to create a ProcessMonitor
and a corresponding ProcessNotify
object. Each ProcessMonitor runs as it own actor and upon receiving data will call its corresponding ProcessNotify
's method.
The following program will spawn an external program and write to it's STDIN. Output received on STDOUT of the child process is forwarded to the ProcessNotify client and printed.
use "process" use "files" actor Main new create(env: Env) => // create a notifier let client = ProcessClient(env) let notifier: ProcessNotify iso = consume client // define the binary to run try let path = FilePath(env.root as AmbientAuth, "/bin/cat")? // define the arguments; first arg is always the binary name let args: Array[String] val = ["cat"] // define the environment variable for the execution let vars: Array[String] val = ["HOME=/"; "PATH=/bin"] // create a ProcessMonitor and spawn the child process let auth = env.root as AmbientAuth let pm: ProcessMonitor = ProcessMonitor(auth, auth, consume notifier, path, args, vars) // write to STDIN of the child process pm.write("one, two, three") pm.done_writing() // closing stdin allows cat to terminate else env.out.print("Could not create FilePath!") end // define a client that implements the ProcessNotify interface class ProcessClient is ProcessNotify let _env: Env new iso create(env: Env) => _env = env fun ref stdout(process: ProcessMonitor ref, data: Array[U8] iso) => let out = String.from_array(consume data) _env.out.print("STDOUT: " + out) fun ref stderr(process: ProcessMonitor ref, data: Array[U8] iso) => let err = String.from_array(consume data) _env.out.print("STDERR: " + err) fun ref failed(process: ProcessMonitor ref, err: ProcessError) => match err | ExecveError => _env.out.print("ProcessError: ExecveError") | PipeError => _env.out.print("ProcessError: PipeError") | ForkError => _env.out.print("ProcessError: ForkError") | WaitpidError => _env.out.print("ProcessError: WaitpidError") | WriteError => _env.out.print("ProcessError: WriteError") | KillError => _env.out.print("ProcessError: KillError") | CapError => _env.out.print("ProcessError: CapError") | Unsupported => _env.out.print("ProcessError: Unsupported") else _env.out.print("Unknown ProcessError!") end fun ref dispose(process: ProcessMonitor ref, child_exit_code: I32) => let code: I32 = consume child_exit_code _env.out.print("Child exit code: " + code.string())
The ProcessMonitor supports spawning processes on Linux, FreeBSD and OSX. Processes are not supported on Windows and attempting to use them will cause a runtime error.
Document waitpid behaviour (stops world)
© 2016-2018, The Pony Developers
© 2014-2015, Causality Ltd.
Licensed under the BSD 2-Clause License.
https://stdlib.ponylang.io/process--index