Introduction

lua-subprocess is a Lua module that allows you to create child processes and communicate with them. The API is based on Python’s subprocess module, but is not yet as complete.

Compatibility

Tested under Windows, Linux and Wine. Needs more testing.

Functions

subprocess.popen { arg1, arg2, …, [options…] }

Creates a child process with the arguments arg1, arg2 etc. Options are table items with string keys. The valid options are:

  • executable - If set, this is used as the actual executable to run, while arg1 becomes argv[0] of the child process. If not set, arg1 is used as the executable name.

  • stdin, stdout, stderr - These identify what to use as the standard input/output/error files of the child process. If not specified, the handle(s) from the parent process are used. Each of these options can have the following types:

    • string - the option specifies a filename that is opened for reading (for stdin) or for writing (for stdout or stderr).

    • number - specifies an open file to use. The file is not closed by popen in the parent process. In POSIX, this value is a file descriptor. In Windows, this value is a Windows API handle.

    • FILE* - a Lua file object can be used. This file is not closed by popen in the parent process. The following constants can also be used:

    • subprocess.PIPE - a pipe is created, and the relevant end is given to the child process. A Lua file object is placed in the returned proc object. For stdin, the read end is given to the child process and stdin is set to a writable file in the proc object. For stdout or stderr, the write end is given to the child process and stdout/stderr is set to a readable file in the proc object.

    • subprocess.STDOUT (only for stderr) - This can be used to redirect the standard error file to the standard output.

  • close_fds (boolean) If true, all file descriptors (except standard input, output and error) are closed after forking, but before calling exec, so that the child process doesn’t inherit these file descriptors. On Windows, this does nothing.

  • cwd (string) Names a directory for the child process to be run in. subprocess.popen can throw Lua errors when something goes horribly wrong. For normal errors, however, it returns nil, errormsg, errno (errno may or may not be nil, depending on the nature of the error).

Return value

On success, returns a proc object (see below). On failure, returns nil, errormsg, errno.

subprocess.call { arg1, arg2, …, [options…] }

Creates a child process in the same way as subprocess.popen but waits for the child to finish executing, then sets and returns the exitcode.

Warning
Do not set stdin, stdout or stderr to subprocess.PIPE when calling subprocess.call, as it will deadlock when a pipe buffer is filled.
Return value

Returns exitcode. See: exitcode.

subprocess.call_capture { arg1, arg2, …, [options…] }

Creates a child process in the same way as subprocess.popen but reads all data from the child’s standard output and returns it. If you want to capture stderr as well, set stderr to subprocess.STDOUT.

Warning
Do not set stderr to subprocess.PIPE, it can deadlock.
Warning
subprocess.call_capture captures all the child process’s output into memory, so if the child produces a huge amount of output, memory might be exhausted.
Return value

Returns exitcode, content where content is a string containing the captured output.

subprocess.wait()

Waits for any child process to exit.

Return value

On success, returns proc, exitcode, pid. I’m not sure why you’d want the pid after the process has finished, though.

On failure, returns nil, errormsg.

Warning
On POSIX operating systems, subprocess.wait calls the wait system function. If you create child processes without using the subprocess module, and the wait system call returns a pid without a corresponding proc object, then the returned proc object will be nil. Furthermore, the process will be removed from the process table and the waitpid system call should not be used for that pid again.

Proc objects

proc.pid

This is set to the process identifier of the child.

Warning
On POSIX systems, do not use this value with the waitpid system call, because you will make the subprocess module use an invalid pid in future system calls. In fact, the wait system call will have this effect too, so don’t use it while subprocess’s child processes are running.

proc.stdin, proc.stdout, proc.stderr

These are set to file objects if the corresponding option passed to subprocess.popen, was set to subprocess.PIPE. Note that if the stderr option was set to subprocess.STDOUT, proc.stderr will not be set.

proc.exitcode

After proc:poll, proc:wait or subprocess.wait discovers the child process has terminated, this field is set to the exit code of the child process. Before then, it is nil. If proc.exitcode < 0 then the child was killed by signal number -proc.exitcode.

proc:poll()

Checks if the child process has terminated. If the child process has terminated, this sets proc.exitcode and returns it. If the child process is still running, this returns nil.

proc:wait()

Waits for the child process to terminate, then sets and returns the exitcode field.

proc:send_signal(sig) (POSIX only)

Sends a signal to the child process.

proc:terminate()

Terminates the child process. On POSIX, itsends SIGTERM. On Windows, it calls TerminateProcess.

proc:kill()

Kills the child process. On POSIX, it sends SIGKILL. On Windows, it is the same as proc:terminate().

TODO

  • Support of other operating systems.

  • Deadlock-free way of communicating.