20.4 Creating Communicating Processes
ECLiPSe provides all the necessary built-ins needed to create UNIX processes
and establish communication between them.
A ECLiPSe process can communicate with other processes via streams and by
sending and receiving signals.
20.4.1 Process creation
The built-ins of the exec group and sh/1
fork a new process and execute the command given as the first argument.
Sorted by their versatility, there are:
With sh/1 (or its synonym system/1) it is possible to
call and execute any UNIX command from withing ECLiPSe.
However it is not possible to communicate with the process.
Moreover, the ECLiPSe process just waits until the command has been executed.
- exec(Command, Streams)
- exec(Command, Streams, ProcessId)
- exec_group(Command, Streams, ProcessId)
The exec group makes it possible to set up communication links
with the child process by specifying the Streams argument.
It is a list of the form
and specifies which ECLiPSe stream should be connected to the
stdin, stdout or stderr of the child respectively.
Unless null is specified, this will establish pipes to be
created between the ECLiPSe process and the child.
On Berkeley UNIX systems the streams can be specified as sigio(Stream)
which will setup the pipe such that the signal sigio is issued
every time new data appears on the pipe.
Thus, by defining a suitable interrupt handler, it is possible to service this
stream in a completely asynchronous way.
[Stdin, Stdout, Stderr]
20.4.2 Process control
The sh/1 and exec/2 built-ins both block the ECLiPSe process until
the child has finished.
For more sophisticated applications, the processes have to run in parallel
and be synchronised explicitly.
This can be achieved with exec/3 or exec_group/3.
These return immediately after having created the child process and
unify its process identifier (Pid) with the their argument.
The Pid can be used to
The difference between exec/3 and exec_group/3 is
that the latter creates a
new process group for the child, such that the child does not get the
interrupt, hangup and kill signals that are sent to the parent.
send signals to the process, using the built-in kill(Pid, Signal)
- wait for the process to terminate and obtain its return status
The process identifier of the running ECLiPSe and of its parent process are
available as the global flags pid and ppid respectively.
They can be accessed using get_flag/2 or env/0.
Here is an example of how to connect the UNIX utility bc (the
arbitrary-precision arithmetic language) to a ECLiPSe process.
We first create the process with two pipes for the child's standard input
Then, by writing and reading these streams, the processes can communicate in
a straightforward way. Note that it is usually necessary to flush the
output after writing into a pipe:
In this example the child process can be terminated by closing its standard
input (in other cases it may be necessary to send a signal).
The built-in wait/2 is then used to wait for the process to terminate
and to obtain its exit status.
Don't forget to close the ECLiPSe streams that were opend by exec/3:
[eclipse 1]: exec(bc, [in,out], P).
P = 9759
[eclipse 2]: writeln(in, "12345678902321 * 2132"), flush(in).
[eclipse 3]: read_string(out, "\n", _, Result).
Result = "26320987419748372"
[eclipse 4]: close(in), wait(P,S).
P = 9759
S = 0 More? (;)
[eclipse 5]: at_eof(out), close(out).
20.4.3 Interprocess Signals
The UNIX (or the appropriate Windows) signals are all mapped to ECLiPSe interrupts.
Their names and numbers may vary on different machines.
Refer to the operating system documentation for details.
The way to deal with incoming signals is to define a Prolog or external
predicate and declare it as the interrupt handler for this interrupt
Interrupt handlers can be established for all signals except those that are
not allowed to be caught by the process (like e.g. the kill signal 9).
For a description of event handling in general see chapter 13.
For explicitly sending signals to other processes kill/2 is provided,
which is a direct interface to the UNIX system call kill(2).
Note that some signals can be set up to be raised automatically,
e.g. sigio can be raised when data arrives on a pipe.