elisp: Asynchronous Processes
36.4 Creating an Asynchronous Process
=====================================
In this section, we describe how to create an “asynchronous process”.
After an asynchronous process is created, it runs in parallel with
Emacs, and Emacs can communicate with it using the functions described
DONTPRINTYET in the following sections (Input to Processes, and *noteOutput
DONTPRINTYET in the following sections (Input to Processes, and Output
from Processes). Note that process communication is only partially
asynchronous: Emacs sends data to the process only when certain
functions are called, and Emacs accepts data from the process only while
waiting for input or for a time delay.
An asynchronous process is controlled either via a “pty”
(pseudo-terminal) or a “pipe”. The choice of pty or pipe is made when
creating the process, by default based on the value of the variable
‘process-connection-type’ (see below). If available, ptys are usually
preferable for processes visible to the user, as in Shell mode, because
they allow for job control (‘C-c’, ‘C-z’, etc.) between the process and
its children, and because interactive programs treat ptys as terminal
devices, whereas pipes don’t support these features. However, for
subprocesses used by Lisp programs for internal purposes, it is often
better to use a pipe, because pipes are more efficient, and because they
are immune to stray character injections that ptys introduce for large
(around 500 byte) messages. Also, the total number of ptys is limited
on many systems and it is good not to waste them.
-- Function: make-process &rest args
This function is the basic low-level primitive for starting
asynchronous subprocesses. It returns a process object
representing the subprocess. Compared to the more high-level
‘start-process’, described below, it takes keyword arguments, is
more flexible, and allows to specify process filters and sentinels
in a single call.
The arguments ARGS are a list of keyword/argument pairs. Omitting
a keyword is always equivalent to specifying it with value ‘nil’.
Here are the meaningful keywords:
:name NAME
Use the string NAME as the process name; if a process with
this name already exists, then NAME is modified (by appending
‘<1>’, etc.) to be unique.
:buffer BUFFER
Use BUFFER as the process buffer. If the value is ‘nil’, the
subprocess is not associated with any buffer.
:command COMMAND
Use COMMAND as the command line of the process. The value
should be a list starting with the program’s executable file
name, followed by strings to give to the program as its
arguments. If the first element of the list is ‘nil’, Emacs
opens a new pseudoterminal (pty) and associates its input and
output with BUFFER, without actually running any program; the
rest of the list elements are ignored in that case.
:coding CODING
If CODING is a symbol, it specifies the coding system to be
used for both reading and writing of data from and to the
connection. If CODING is a cons cell ‘(DECODING . ENCODING)’,
then DECODING will be used for reading and ENCODING for
writing. The coding system used for encoding the data written
to the program is also used for encoding the command-line
arguments (but not the program itself, whose file name is
encoded as any other file name; file-name-coding-system
Encoding and I/O.).
If CODING is ‘nil’, the default rules for finding the coding
system will apply. Default Coding Systems.
:connection-type TYPE
Initialize the type of device used to communicate with the
subprocess. Possible values are ‘pty’ to use a pty, ‘pipe’ to
use a pipe, or ‘nil’ to use the default derived from the value
of the ‘process-connection-type’ variable. This parameter and
the value of ‘process-connection-type’ are ignored if a
non-‘nil’ value is specified for the ‘:stderr’ parameter; in
that case, the type will always be ‘pipe’.
:noquery QUERY-FLAG
Initialize the process query flag to QUERY-FLAG. Query
Before Exit.
:stop STOPPED
If STOPPED is non-‘nil’, start the process in the stopped
state.
:filter FILTER
Initialize the process filter to FILTER. If not specified, a
default filter will be provided, which can be overridden
later. Filter Functions.
:sentinel SENTINEL
Initialize the process sentinel to SENTINEL. If not
specified, a default sentinel will be used, which can be
overridden later. Sentinels.
:stderr STDERR
Associate STDERR with the standard error of the process. A
non-‘nil’ value should be either a buffer or a pipe process
created with ‘make-pipe-process’, described below.
The original argument list, modified with the actual connection
information, is available via the ‘process-contact’ function.
The current working directory of the subprocess is set to the
current buffer’s value of ‘default-directory’ if that is local (as
determined by ‘unhandled-file-name-directory’), or "~" otherwise.
If you want to run a process in a remote direcotry use
‘start-file-process’.
-- Function: make-pipe-process &rest args
This function creates a bidirectional pipe which can be attached to
a child process. This is useful with the ‘:stderr’ keyword of
‘make-process’. The function returns a process object.
The arguments ARGS are a list of keyword/argument pairs. Omitting
a keyword is always equivalent to specifying it with value ‘nil’.
Here are the meaningful keywords:
:name NAME
Use the string NAME as the process name. As with
‘make-process’, it is modified if necessary to make it unique.
:buffer BUFFER
Use BUFFER as the process buffer.
:coding CODING
If CODING is a symbol, it specifies the coding system to be
used for both reading and writing of data from and to the
connection. If CODING is a cons cell ‘(DECODING . ENCODING)’,
then DECODING will be used for reading and ENCODING for
writing.
If CODING is ‘nil’, the default rules for finding the coding
system will apply. Default Coding Systems.
:noquery QUERY-FLAG
Initialize the process query flag to QUERY-FLAG. Query
Before Exit.
:stop STOPPED
If STOPPED is non-‘nil’, start the process in the stopped
state.
:filter FILTER
Initialize the process filter to FILTER. If not specified, a
default filter will be provided, which can be changed later.
Filter Functions.
:sentinel SENTINEL
Initialize the process sentinel to SENTINEL. If not
specified, a default sentinel will be used, which can be
changed later. Sentinels.
The original argument list, modified with the actual connection
information, is available via the ‘process-contact’ function.
-- Function: start-process name buffer-or-name program &rest args
This function is a higher-level wrapper around ‘make-process’,
exposing an interface that is similar to ‘call-process’. It
creates a new asynchronous subprocess and starts the specified
PROGRAM running in it. It returns a process object that stands for
the new subprocess in Lisp. The argument NAME specifies the name
for the process object; as with ‘make-process’, it is modified if
necessary to make it unique. The buffer BUFFER-OR-NAME is the
buffer to associate with the process.
If PROGRAM is ‘nil’, Emacs opens a new pseudoterminal (pty) and
associates its input and output with BUFFER-OR-NAME, without
creating a subprocess. In that case, the remaining arguments ARGS
are ignored.
The rest of ARGS are strings that specify command line arguments
for the subprocess.
In the example below, the first process is started and runs
(rather, sleeps) for 100 seconds (the output buffer ‘foo’ is
created immediately). Meanwhile, the second process is started,
and given the name ‘my-process<1>’ for the sake of uniqueness. It
inserts the directory listing at the end of the buffer ‘foo’,
before the first process finishes. Then it finishes, and a message
to that effect is inserted in the buffer. Much later, the first
process finishes, and another message is inserted in the buffer for
it.
(start-process "my-process" "foo" "sleep" "100")
⇒ #<process my-process>
(start-process "my-process" "foo" "ls" "-l" "/bin")
⇒ #<process my-process<1>>
---------- Buffer: foo ----------
total 8336
-rwxr-xr-x 1 root root 971384 Mar 30 10:14 bash
-rwxr-xr-x 1 root root 146920 Jul 5 2011 bsd-csh
...
-rwxr-xr-x 1 root root 696880 Feb 28 15:55 zsh4
Process my-process<1> finished
Process my-process finished
---------- Buffer: foo ----------
-- Function: start-file-process name buffer-or-name program &rest args
Like ‘start-process’, this function starts a new asynchronous
subprocess running PROGRAM in it, and returns its process object.
The difference from ‘start-process’ is that this function may
invoke a file handler based on the value of ‘default-directory’.
This handler ought to run PROGRAM, perhaps on the local host,
perhaps on a remote host that corresponds to ‘default-directory’.
In the latter case, the local part of ‘default-directory’ becomes
the working directory of the process.
This function does not try to invoke file name handlers for PROGRAM
or for the rest of ARGS.
Depending on the implementation of the file handler, it might not
be possible to apply ‘process-filter’ or ‘process-sentinel’ to the
DONTPRINTYET resulting process object. Filter Functions, and *noteDONTPRINTYET resulting process object. Filter Functions, and
Sentinels.
Some file handlers may not support ‘start-file-process’ (for
example the function ‘ange-ftp-hook-function’). In such cases,
this function does nothing and returns ‘nil’.
-- Function: start-process-shell-command name buffer-or-name command
This function is like ‘start-process’, except that it uses a shell
to execute the specified COMMAND. The argument COMMAND is a shell
command string. The variable ‘shell-file-name’ specifies which
shell to use.
The point of running a program through the shell, rather than
directly with ‘make-process’ or ‘start-process’, is so that you can
employ shell features such as wildcards in the arguments. It
follows that if you include any arbitrary user-specified arguments
in the command, you should quote them with ‘shell-quote-argument’
first, so that any special shell characters do _not_ have their
special shell meanings. Shell Arguments. Of course, when
executing commands based on user input you should also consider the
security implications.
-- Function: start-file-process-shell-command name buffer-or-name
command
This function is like ‘start-process-shell-command’, but uses
‘start-file-process’ internally. Because of this, COMMAND can also
be executed on remote hosts, depending on ‘default-directory’.
-- Variable: process-connection-type
This variable controls the type of device used to communicate with
asynchronous subprocesses. If it is non-‘nil’, then ptys are used,
when available. Otherwise, pipes are used.
The value of ‘process-connection-type’ takes effect when
‘make-process’ or ‘start-process’ is called. So you can specify
how to communicate with one subprocess by binding the variable
around the call to these functions.
Note that the value of this variable is ignored when ‘make-process’
is called with a non-‘nil’ value of the ‘:stderr’ parameter; in
that case, Emacs will communicate with the process using pipes.
(let ((process-connection-type nil)) ; use a pipe
(start-process ...))
To determine whether a given subprocess actually got a pipe or a
pty, use the function ‘process-tty-name’ (Process
Information).