Processes (multitasking)

Author(s): Jose F. Morales.

This library offers predicates to create, communicate, and synchronize with child processes. The child processes are duplicates of the parent process, based on the fork() function from POSIX-compatible operating systems (see man page for a precise description of the non-inherited process attributes).

The child process can execute a given goal (in a clone of the parent process) or start an external program.

Contrary to threads, processes have a separate address space and communication must be performed via inter-process communication mechanisms. This is useful for executing external programs, or implementing coarse-grained parallelism and concurrency.

  • Process creation via fork() is relatively costly. Use only when address separation is necessary. Consider other concurrency primitives otherwise.
  • Channels connected to in-memory terms are transmited via pipes or temporary files (when needed to avoid deadlock problems).
  • Deadlock problems may still appear if the user specifies two or more pipe(_) channels for the same process (data must be send/received concurrently).
  • The current implementation is not protected against Prolog signals (it can leak resources, including zombie processes, if interrupted by signals).
  • Communication is currently only supported via file system, file descriptors, and sockets.
  • Other mechanisms like file locks, semaphores, message queues, shared memory, etc. are not yet implemented.
  • Arguments do not accept wildcards. See predicates in library(glob) for glob expansions (shell wildcard patterns).

Documentation on exports

REGTYPE

Usage:

A process handler

    REGTYPE

    The predicate process_call/3 waits for process completion, throwing an exception if the return code is different than 0. This default exit behaviour can be controlled with the following options:

  • status(ReturnCode): unifies return code with ReturnCode upon process completion (no exception is thrown, may fail).
  • background(Process): execute asynchronously in background; most errors (including input/output) are delayed to process_join/1.
  • setsid: call setsid() on the child to create a new session (useful to create daemon processes http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html)
  • The process standard input, output, and error file descriptors (streams from the Prolog side) can be bind to several process_channel/1:

  • stdin(Channel): set channel for standard input
  • stdout(Channel): set channel for standard output
  • stderr(Channel): set channel for standard error
  • The environment of the process can be modified with the following options:

  • cwd(Dir): execute command at the Dir directory (does not affect relative path for input/output redirection).
  • env(Env): modify the specified environment variables.
  • noenv(Env): unset the specified environment variables.
  • Usage:

    Options that control command execution

      REGTYPE

      Usage:

      Command for process_call/3

        REGTYPE

        Usage:

        Argument for process_call/3

          PREDICATE

          Usage:process_call(Cmd,Args,Opts)

          Execute a command in a child process, where Cmd is the executable path. Use path(Exec) for executing a program Exec reachable from the PATH environment variable

          • The following properties should hold at call time:
            (process:process_cmd/1)Command for process_call/3
            (basic_props:list/2)Args is a list of process_args.
            (basic_props:list/2)Opts is a list of process_options.

          PREDICATE

          Usage:process_pid(Process,Pid)

          The POSIX PID of the process Process.

          • The following properties should hold at call time:
            (process:process/1)A process handler
            (basic_props:int/1)Pid is an integer.

          PREDICATE

          Usage:process_is_joined(Process)

          The process has already been joined.

          • The following properties should hold at call time:
            (process:process/1)A process handler

          PREDICATE

          Usage:process_join(Process)

          Wait for completion of process Process.

          • The following properties should hold at call time:
            (process:process/1)A process handler

          PREDICATE

          Usage:process_terminate(Process)

          Sends POSIX signal SIGTERM to the process Process, which asks politely for process termination.

          • The following properties should hold at call time:
            (process:process/1)A process handler

          PREDICATE

          Usage:process_kill(Process)

          Sends POSIX signal SIGKILL to the process Process, which forces process termination.

          • The following properties should hold at call time:
            (process:process/1)A process handler

          PREDICATE

          Usage:process_send_signal(Process,Signal)

          Sends POSIX signal Signal to process Process.

          • The following properties should hold at call time:
            (process:process/1)A process handler
            (basic_props:int/1)Signal is an integer.

          PREDICATE

          Usage:process_fork(Goal,Opts)

          Execute Goal in a forked process.

          • The following properties should hold at call time:
            (basic_props:callable/1)Goal is a term which represents a goal, i.e., an atom or a structure.
            (basic_props:list/2)Opts is a list of process_options.
          Meta-predicate with arguments: process_fork(goal,?).

          PREDICATE

          Usage:process_pipe(Cmd,Opts)

          Execute the list Cmds of process_call/3, connecting standard input and output of consecutive processes with pipes.

          Options are passed as follows: input redirection options are applied to the first process; output redirection and status are applied to the last process; the rest of options are applied to all commands. Background execution is not currently supported (see internal documentation for details).

            Known bugs and planned improvements

            • (feature) Poll if a process has terminated
            • (feature) Support more IPC primitives (file locks, semaphores, shared memory, etc.).
            • (feature) Fix asynchronous data transmission using POSIX select? We may avoid temporary files then.
            • (feature) Complete support for daemons (see example)
            • (feature) Put together with other concurrency and parallelism libraries in Ciao
            • (performance) Consider using posix_spawn for exec (faster, works in systems without MMU).
            • (performance) Write benchmarks (see internal documentation)
            • (stability) Protect against signals
            • (stability) Pending safety checks? Close file descriptors in child process?
            • (mingw) Add Windows specific options to create processes in a new console and create new process groups. Process groups will be necessary for killing subprocess using process_kill/1.
            • Background execution is not supported in process_pipe/2. That requires the creation of a new process abstraction to group together several processes. This compound process would be user-based and then, it is not clear that it belongs to this module.