Module: Spawn

New in version 1.12: Spawn module added.

Support launching and interacting with other programs.

Using functions in this module, one can create a subprocess and possibly capture its output. It is also possible to provide input to a subprocess.

To start a subprocess, use spawn or spawnshell. To wait for the subprocess process to finish, use the subprocess.wait or subprocess.communicate functions.

This example program produces a listing of files in the current directory with names that begin with test. by using the ls command. The output will be mixed in with the Chapel program’s output.

use Spawn;

var sub = spawn(["ls", "test.*"]);
sub.wait();

This version also runs the ls command but uses a pipe to read the output from the ls command.

use Spawn;

var sub = spawn(["ls", "test.*"], stdout=PIPE);

var line:string;
while sub.stdout.readline(line) {
  write("ls returned: ", line);
}

sub.wait();

Finally, this version uses pipes to provide input to a subprocess in addition to capturing its output. This version uses the cat command, which just prints back its input.

use Spawn;

var sub = spawn(["cat"], stdin=PIPE, stdout=PIPE);

sub.stdin.writeln("Hello");
sub.stdin.writeln("World");

sub.communicate();

var line:string;
while sub.stdout.readline(line) {
  write("Got line: ", line);
}
// prints out:
// Got line: Hello
// Got line: World

Note

As of Chapel v1.12, creating a subprocess that uses PIPE to provide input or capture output does not work when using the ugni communications layer and when using more than one locale. In this circumstance, the program will halt with an error message. These scenarios do work when using GASNet instead of the ugni layer.

record subprocess

This record represents a subprocess.

param kind: iokind

The kind of a subprocess is used to create the types for any channels that are necessary.

param locking: bool

As with kind, this value is used to create the types for any channels that are necessary.

var pid: int(64)

The Process ID number of the spawned process

var running: bool

false if this library knows that the subprocess is not running

var exit_status: int

The exit status from the subprocess, or possibly a value >= 256 if there was en error when creating the subprocess

const FORWARD = QIO_FD_FORWARD

FORWARD indicates that the child process should inherit the stdin/stdout/stderr of this process.

const CLOSE = QIO_FD_CLOSE

CLOSE indicates that the child process should close its stdin/stdout/stderr.

const PIPE = QIO_FD_PIPE

PIPE indicates that the spawn operation should set up a pipe between the parent process and the child process so that the parent process can provide input to the child process or capture its output.

const STDOUT = QIO_FD_TO_STDOUT

STDOUT indicates that the stderr stream of the child process should be forwarded to its stdout stream.

proc spawn(args: [] string, env: [] string = Spawn.empty_env, executable = "", stdin: ?t = FORWARD, stdout: ?u = FORWARD, stderr: ?v = FORWARD, param kind = iokind.dynamic, param locking = true)

Create a subprocess.

Arguments:
  • args – An array of strings storing the command to run and its arguments. The command to run is always the first argument. The command could be found in the current PATH or it could be a full path to a file to execute. If the executable argument is set, the first argument will be the name of the spawned program provided to that program and typically shown in process listings.
  • env – An array of strings storing the environment to use when spawning the child process instead of forwarding the current environment. By default, this argument is an empty array. In that case, the current environment will be forwarded to the child process.
  • executable – By default, the executable argument is “”. In that case, the program to launch is the first element of the args array. If the executable argument is provided, it will be used instead of the first element of the args array as the program to launch. In either case, the program could be found by searching the PATH.
  • stdin – indicates how the standard input of the child process should be handled. It could be FORWARD, CLOSE, PIPE, or a file descriptor number to use. Defaults to FORWARD.
  • stdout – indicates how the standard output of the child process should be handled. It could be FORWARD, CLOSE, PIPE, or a file descriptor number to use. Defaults to FORWARD.
  • stderr – indicates how the standard error of the child process should be handled. It could be FORWARD, CLOSE, PIPE, STDOUT, or a file descriptor number to use. Defaults to FORWARD.
  • kind – What kind of channels should be created when PIPE is used. This argument is used to set subprocess.kind in the resulting subprocess. Defaults to IO.iokind.dynamic.
  • locking – Should channels created use locking? This argument is used to set subprocess.locking in the resulting subprocess. Defaults to true.
Returns:

a subprocess with kind and locking set according to the arguments.

proc spawnshell(command: string, env: [] string = Spawn.empty_env, stdin: ?t = FORWARD, stdout: ?u = FORWARD, stderr: ?v = FORWARD, executable = "/bin/sh", shellarg = "-c", param kind = iokind.dynamic, param locking = true)

Create a subprocess by invoking a shell.

Note

Since the command string is passed to a shell, it is very unsecure to pass user input to this command without proper quoting.

Arguments:
  • command – A string representing the command to run. This string will be interpreted by the shell.
  • env – An array of strings storing the environment to use when spawning the child process instead of forwarding the current environment. By default, this argument is an empty array. In that case, the current environment will be forwarded to the child process.
  • stdin – indicates how the standard input of the child process should be handled. It could be FORWARD, CLOSE, PIPE, or a file descriptor number to use. Defaults to FORWARD.
  • stdout – indicates how the standard output of the child process should be handled. It could be FORWARD, CLOSE, PIPE, or a file descriptor number to use. Defaults to FORWARD.
  • stderr – indicates how the standard error of the child process should be handled. It could be FORWARD, CLOSE, PIPE, STDOUT, or a file descriptor number to use. Defaults to FORWARD.
  • executable – By default, the executable argument is “/bin/sh”. That directs the subprocess to run the /bin/sh shell in order to interpret the command string.
  • shellarg – An argument to pass to the shell before the command string. By default this is “-c”.
  • kind – What kind of channels should be created when PIPE is used. This argument is used to set subprocess.kind in the resulting subprocess. Defaults to IO.iokind.dynamic.
  • locking – Should channels created use locking? This argument is used to set subprocess.locking in the resulting subprocess. Defaults to true.
Returns:

a subprocess with kind and locking set according to the arguments.

proc subprocess.poll(out error: syserr)

Check to see if a child process has terminated. If the child process has terminated, after this call, running will be false.

proc subprocess.wait(out error: syserr)

Wait for a child process to complete. After this function returns, running is false and exit_status stores the exit code returned by the subprocess.

Note

Use subprocess.communicate instead of this function when using PIPE for stdin, stdout, or stderr. This function does not try to send any buffered input to the child process and so could result in a hang if the child process is waiting for input to finish. Similarly, this function does not consume the output from the child process and so the child process could hang while waiting to write data to its output while the parent process is waiting for it to complete (and not consuming its output).

Arguments:error – optional argument to capture any error encountered when waiting for the child process.
proc subprocess.communicate(out error: syserr)

Wait for a child process to complete. After this function returns, running is false and exit_status stores the exit code returned by the subprocess.

This function handles cases in which stdin, stdout, or stderr for the child process is PIPE by writing any input to the child process and buffering up the output of the child process as necessary while waiting for it to terminate.

Arguments:error – optional argument to capture any error encountered when waiting for the child process.